diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index 7e6ce9b5..2c800ef0 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -716,71 +716,25 @@ public struct BridgeJSLink { signature: ClosureSignature, functionName: String ) throws -> [String] { - let printer = CodeFragmentPrinter() - let context = IntrinsicJSFragment.PrintCodeContext( - scope: JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry), - printer: printer, - cleanupCode: CodeFragmentPrinter() - ) + let thunkBuilder = ImportedThunkBuilder(context: .exportSwift, intrinsicRegistry: intrinsicRegistry) + thunkBuilder.parameterNames.append("callbackId") + thunkBuilder.body.write("const callback = \(JSGlueVariableScope.reservedSwift).memory.getObject(callbackId);") - // Build parameter list for invoke function - var invokeParams: [String] = ["callbackId"] for (index, paramType) in signature.parameters.enumerated() { - if case .nullable = paramType { - invokeParams.append("param\(index)IsSome") - invokeParams.append("param\(index)Value") - } else { - invokeParams.append("param\(index)Id") - } + let paramName = "param\(index)" + try thunkBuilder.liftParameter(param: Parameter(label: nil, name: paramName, type: paramType)) } - printer.nextLine() - printer.write("bjs[\"\(functionName)\"] = function(\(invokeParams.joined(separator: ", "))) {") - try printer.indent { - printer.write("try {") - try printer.indent { - printer.write("const callback = \(JSGlueVariableScope.reservedSwift).memory.getObject(callbackId);") + let returnExpr = try thunkBuilder.call(calleeExpr: "callback", returnType: signature.returnType) - for (index, paramType) in signature.parameters.enumerated() { - let fragment = try IntrinsicJSFragment.closureLiftParameter(type: paramType) - let args: [String] - if case .nullable = paramType { - args = ["param\(index)IsSome", "param\(index)Value", "param\(index)"] - } else { - args = ["param\(index)Id", "param\(index)"] - } - _ = try fragment.printCode(args, context) - } - - let callbackParams = signature.parameters.indices.map { "param\($0)" }.joined(separator: ", ") - printer.write("const result = callback(\(callbackParams));") - - // Type check if needed (for example, formatName requires string return) - switch signature.returnType { - case .string: - printer.write("if (typeof result !== \"string\") {") - printer.indent { - printer.write("throw new TypeError(\"Callback must return a string\");") - } - printer.write("}") - default: - break - } - - let returnFragment = try IntrinsicJSFragment.closureLowerReturn(type: signature.returnType) - _ = try returnFragment.printCode(["result"], context) - } - printer.write("} catch (error) {") - try printer.indent { - printer.write("\(JSGlueVariableScope.reservedSetException)?.(error);") - let errorFragment = IntrinsicJSFragment.closureErrorReturn(type: signature.returnType) - _ = try errorFragment.printCode([], context) - } - printer.write("}") - } - printer.write("};") + var functionLines = thunkBuilder.renderFunction( + name: nil, + returnExpr: returnExpr, + returnType: signature.returnType + ) + functionLines[0] = "bjs[\"\(functionName)\"] = " + functionLines[0] - return printer.lines + return functionLines } /// Generates a lower_closure_* function that wraps a Swift closure for JavaScript @@ -789,46 +743,27 @@ public struct BridgeJSLink { functionName: String ) throws -> [String] { let printer = CodeFragmentPrinter() - let context = IntrinsicJSFragment.PrintCodeContext( - scope: JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry), - printer: printer, - cleanupCode: CodeFragmentPrinter() + let builder = ExportedThunkBuilder( + effects: Effects(isAsync: false, isThrows: true), + hasDirectAccessToSwiftClass: false, + intrinsicRegistry: intrinsicRegistry ) + builder.parameterForwardings.append("boxPtr") printer.write( "const \(functionName) = function(\(signature.parameters.indices.map { "param\($0)" }.joined(separator: ", "))) {" ) try printer.indent { - var invokeArgs: [String] = ["boxPtr"] - + // Lower parameters using shared thunk builder for (index, paramType) in signature.parameters.enumerated() { let paramName = "param\(index)" - let fragment = try IntrinsicJSFragment.lowerParameter(type: paramType) - let lowered = try fragment.printCode([paramName], context) - invokeArgs.append(contentsOf: lowered) + try builder.lowerParameter(param: Parameter(label: nil, name: paramName, type: paramType)) } - // Call the Swift invoke function let invokeCall = - "\(JSGlueVariableScope.reservedInstance).exports.invoke_swift_closure_\(signature.moduleName)_\(signature.mangleName)(\(invokeArgs.joined(separator: ", ")))" - let invokeResultName = "invokeResult" - printer.write("const \(invokeResultName) = \(invokeCall);") - - printer.write("if (\(JSGlueVariableScope.reservedStorageToReturnException)) {") - printer.indent { - printer.write( - "const error = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(JSGlueVariableScope.reservedStorageToReturnException));" - ) - printer.write( - "\(JSGlueVariableScope.reservedSwift).memory.release(\(JSGlueVariableScope.reservedStorageToReturnException));" - ) - printer.write("\(JSGlueVariableScope.reservedStorageToReturnException) = undefined;") - printer.write("throw error;") - } - printer.write("}") - - let returnFragment = try IntrinsicJSFragment.closureLiftReturn(type: signature.returnType) - _ = try returnFragment.printCode([invokeResultName], context) + "invoke_swift_closure_\(signature.moduleName)_\(signature.mangleName)" + let returnExpr = try builder.call(abiName: invokeCall, returnType: signature.returnType) + builder.renderFunctionBody(into: printer, returnExpr: returnExpr) } printer.write("};") @@ -1291,7 +1226,7 @@ public struct BridgeJSLink { let scope: JSGlueVariableScope let context: IntrinsicJSFragment.PrintCodeContext - init(effects: Effects, intrinsicRegistry: JSIntrinsicRegistry) { + init(effects: Effects, hasDirectAccessToSwiftClass: Bool = true, intrinsicRegistry: JSIntrinsicRegistry) { self.effects = effects self.scope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) self.body = CodeFragmentPrinter() @@ -1299,7 +1234,8 @@ public struct BridgeJSLink { self.context = IntrinsicJSFragment.PrintCodeContext( scope: scope, printer: body, - cleanupCode: cleanupCode + cleanupCode: cleanupCode, + hasDirectAccessToSwiftClass: hasDirectAccessToSwiftClass ) } @@ -2221,13 +2157,13 @@ extension BridgeJSLink { } func renderFunction( - name: String, + name: String?, returnExpr: String?, returnType: BridgeType ) -> [String] { let printer = CodeFragmentPrinter() - printer.write("function \(name)(\(parameterNames.joined(separator: ", "))) {") + printer.write("function\(name.map { " \($0)" } ?? "")(\(parameterNames.joined(separator: ", "))) {") printer.indent { printer.write("try {") printer.indent { @@ -2259,7 +2195,7 @@ extension BridgeJSLink { return try call(name: name, fromObjectExpr: "imports", returnType: returnType) } - private func call(calleeExpr: String, returnType: BridgeType) throws -> String? { + func call(calleeExpr: String, returnType: BridgeType) throws -> String? { let callExpr = "\(calleeExpr)(\(parameterForwardings.joined(separator: ", ")))" return try self.call(callExpr: callExpr, returnType: returnType) } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 510a361f..9f1eddfd 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -154,6 +154,9 @@ struct IntrinsicJSFragment: Sendable { var printer: CodeFragmentPrinter /// The printer to print the code that is expected to be executed at the end of the caller of the fragment. var cleanupCode: CodeFragmentPrinter + /// Whether the fragment has direct access to the SwiftHeapObject classes. + /// If false, the fragment needs to use `_exports[""]` to access the class. + var hasDirectAccessToSwiftClass: Bool = true func with(_ keyPath: WritableKeyPath, _ value: T) -> PrintCodeContext { var new = self @@ -613,7 +616,9 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in - return ["\(name).__construct(\(arguments[0]))"] + return [ + "\(context.hasDirectAccessToSwiftClass ? name : "_exports['\(name)']").__construct(\(arguments[0]))" + ] } ) } @@ -944,11 +949,9 @@ struct IntrinsicJSFragment: Sendable { static func optionalLiftReturn( wrappedType: BridgeType, - context: BridgeContext = .exportSwift, kind: JSOptionalKind ) -> IntrinsicJSFragment { let absenceLiteral = kind.absenceLiteral - let bridgeContext = context return IntrinsicJSFragment( parameters: [], printCode: { arguments, context in @@ -980,7 +983,7 @@ struct IntrinsicJSFragment: Sendable { ) printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject) = undefined;") let constructExpr = - bridgeContext == .exportSwift + context.hasDirectAccessToSwiftClass ? "\(className).__construct(\(pointerVar))" : "_exports['\(className)'].__construct(\(pointerVar))" printer.write( @@ -1349,619 +1352,6 @@ struct IntrinsicJSFragment: Sendable { ) } - // MARK: - Closure Support - - /// Lifts a WASM parameter to JS for passing to a JS callback (invoke_js_callback_*) - static func closureLiftParameter(type: BridgeType) throws -> IntrinsicJSFragment { - switch type { - case .int, .float, .double, .caseEnum: - return IntrinsicJSFragment( - parameters: ["value", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - printer.write("let \(arguments[1]) = \(arguments[0]);") - return [] - } - ) - case .bool: - return IntrinsicJSFragment( - parameters: ["value", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - let baseFragment = boolLiftParameter - let lifted = try baseFragment.printCode([arguments[0]], context) - printer.write("let \(arguments[1]) = \(lifted[0]);") - return [] - } - ) - case .string: - return IntrinsicJSFragment( - parameters: ["objectId", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - let baseFragment = stringLiftParameter - let lifted = try baseFragment.printCode([arguments[0]], context) - printer.write("let \(arguments[1]) = String(\(lifted[0]));") - return [] - } - ) - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - return IntrinsicJSFragment( - parameters: ["objectId", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - let baseFragment = stringLiftParameter - let lifted = try baseFragment.printCode([arguments[0]], context) - printer.write("let \(arguments[1]) = String(\(lifted[0]));") - return [] - } - ) - case .bool: - return IntrinsicJSFragment( - parameters: ["value", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - let baseFragment = boolLiftParameter - let lifted = try baseFragment.printCode([arguments[0]], context) - printer.write("let \(arguments[1]) = \(lifted[0]);") - return [] - } - ) - default: - return IntrinsicJSFragment( - parameters: ["value", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - printer.write("let \(arguments[1]) = \(arguments[0]);") - return [] - } - ) - } - case .jsObject: - return IntrinsicJSFragment( - parameters: ["objectId", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - let objectId = arguments[0] - let targetVar = arguments[1] - printer.write( - "let \(targetVar) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(objectId));" - ) - printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(objectId));") - return [] - } - ) - case .swiftHeapObject(let name): - return IntrinsicJSFragment( - parameters: ["pointer", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - let pointer = arguments[0] - let targetVar = arguments[1] - printer.write("let \(targetVar) = _exports['\(name)'].__construct(\(pointer));") - return [] - } - ) - case .associatedValueEnum(let fullName): - return IntrinsicJSFragment( - parameters: ["caseId", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - let caseId = arguments[0] - let targetVar = arguments[1] - let base = fullName.components(separatedBy: ".").last ?? fullName - printer.write( - "let \(targetVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(caseId));" - ) - return [] - } - ) - case .nullable(let wrappedType, let kind): - return try closureOptionalLiftParameter(wrappedType: wrappedType, kind: kind) - default: - throw BridgeJSLinkError(message: "Unsupported closure parameter type for lifting: \(type)") - } - } - - /// Handles optional parameter lifting for closure invocation. - private static func closureOptionalLiftParameter( - wrappedType: BridgeType, - kind: JSOptionalKind - ) throws -> IntrinsicJSFragment { - let absenceLiteral = kind.absenceLiteral - switch wrappedType { - case .string, .rawValueEnum, .int, .bool, .double, .float, .jsObject, .swiftHeapObject, .caseEnum, - .associatedValueEnum, .closure: - break - default: - throw BridgeJSLinkError( - message: "Unsupported optional wrapped type in closure parameter lifting: \(wrappedType)" - ) - } - - return IntrinsicJSFragment( - parameters: ["isSome", "value", "targetVar"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let isSome = arguments[0] - let value = arguments[1] - let targetVar = arguments[2] - - printer.write("let \(targetVar);") - printer.write("if (\(isSome)) {") - printer.indent() - switch wrappedType { - case .string, .rawValueEnum(_, .string): - let objectLabel = scope.variable("\(targetVar)Object") - printer.write( - "const \(objectLabel) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(value));" - ) - printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(value));") - printer.write("\(targetVar) = String(\(objectLabel));") - case .int, .uint: - printer.write("\(targetVar) = \(value) | 0;") - case .bool: - printer.write("\(targetVar) = \(value) !== 0;") - case .double: - printer.write("\(targetVar) = \(value);") - case .float: - printer.write("\(targetVar) = Math.fround(\(value));") - case .jsObject: - printer.write("\(targetVar) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(value));") - printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(value));") - case .swiftHeapObject(let typeName): - printer.write("\(targetVar) = _exports['\(typeName)'].__construct(\(value));") - case .caseEnum: - printer.write("\(targetVar) = \(value);") - case .rawValueEnum(_, let rawType): - switch rawType { - case .bool: - printer.write("\(targetVar) = \(value) !== 0;") - default: - printer.write("\(targetVar) = \(value);") - } - case .associatedValueEnum(let fullName): - let base = fullName.components(separatedBy: ".").last ?? fullName - printer.write( - "\(targetVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(value));" - ) - case .closure: - printer.write("\(targetVar) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(value));") - printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(value));") - default: - fatalError("Unsupported optional wrapped type in closure parameter lifting: \(wrappedType)") - } - printer.unindent() - printer.write("} else {") - printer.indent() - printer.write("\(targetVar) = \(absenceLiteral);") - printer.unindent() - printer.write("}") - - return [] - } - ) - } - - /// Lowers a JS return value to WASM for returning from callback (invoke_js_callback_*) - static func closureLowerReturn(type: BridgeType) throws -> IntrinsicJSFragment { - switch type { - case .void: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { _, context in - context.printer.write("return;") - return [] - } - ) - case .int, .caseEnum: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - context.printer.write("return \(arguments[0]) | 0;") - return [] - } - ) - case .bool: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - let baseFragment = boolLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], context) - context.printer.write("return \(lowered[0]);") - return [] - } - ) - case .float: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - context.printer.write("return Math.fround(\(arguments[0]));") - return [] - } - ) - case .double: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - context.printer.write("return \(arguments[0]);") - return [] - } - ) - case .string: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - let baseFragment = stringLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], context) - context.printer.write("return \(lowered[0]);") - return [] - } - ) - case .jsObject: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - let baseFragment = jsObjectLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], context) - context.printer.write("return \(lowered[0]);") - return [] - } - ) - case .swiftHeapObject: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - let baseFragment = swiftHeapObjectLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], context) - context.printer.write("return \(lowered[0]);") - return [] - } - ) - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - let baseFragment = stringLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], context) - context.printer.write("return \(lowered[0]);") - return [] - } - ) - case .bool: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - let baseFragment = boolLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], context) - context.printer.write("return \(lowered[0]);") - return [] - } - ) - default: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - context.printer.write("return \(arguments[0]) | 0;") - return [] - } - ) - } - case .associatedValueEnum(let fullName): - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) - let result = arguments[0] - let base = fullName.components(separatedBy: ".").last ?? fullName - let caseIdVar = scope.variable("caseId") - let cleanupVar = scope.variable("cleanup") - printer.write( - "const { caseId: \(caseIdVar), cleanup: \(cleanupVar) } = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(result));" - ) - cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") - printer.write("return \(caseIdVar);") - return [] - } - ) - case .nullable(let wrappedType, _): - return try closureOptionalLowerReturn(wrappedType: wrappedType) - default: - throw BridgeJSLinkError(message: "Unsupported closure return type for lowering: \(type)") - } - } - - /// Handles optional return lowering for closure invocation - private static func closureOptionalLowerReturn(wrappedType: BridgeType) throws -> IntrinsicJSFragment { - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) - let result = arguments[0] - - switch wrappedType { - case .swiftHeapObject: - printer.write("return \(result) ? \(result).pointer : 0;") - case .string: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = \(result);") - printer.write("return;") - case .int, .uint: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = \(result);") - printer.write("return;") - case .bool: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalBool) = \(result);") - printer.write("return;") - case .float: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = \(result);") - printer.write("return;") - case .double: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = \(result);") - printer.write("return;") - case .caseEnum: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = \(result);") - printer.write("return;") - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = \(result);") - printer.write("return;") - case .bool: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalBool) = \(result);") - printer.write("return;") - case .float: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = \(result);") - printer.write("return;") - case .double: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = \(result);") - printer.write("return;") - default: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = \(result);") - printer.write("return;") - } - case .associatedValueEnum(let fullName): - let base = fullName.components(separatedBy: ".").last ?? fullName - let caseIdVar = scope.variable("caseId") - let cleanupVar = scope.variable("cleanup") - printer.write("if (\(result)) {") - printer.indent() - printer.write( - "const { caseId: \(caseIdVar), cleanup: \(cleanupVar) } = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(result));" - ) - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = \(caseIdVar);") - cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") - printer.unindent() - printer.write("} else {") - printer.indent() - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = null;") - printer.unindent() - printer.write("}") - printer.write("return;") - default: - fatalError("Unsupported optional wrapped type in closure return lowering: \(wrappedType)") - } - - return [] - } - ) - } - - /// Lifts a WASM return value to JS from Swift closure (lower_closure_*) - static func closureLiftReturn(type: BridgeType) throws -> IntrinsicJSFragment { - switch type { - case .void: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - let printer = context.printer - printer.write("\(arguments[0]);") - printer.write("return;") - return [] - } - ) - case .int, .caseEnum: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - context.printer.write("return \(arguments[0]) | 0;") - return [] - } - ) - case .bool: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - let baseFragment = boolLiftReturn - let lifted = try baseFragment.printCode([arguments[0]], context) - context.printer.write("return \(lifted[0]);") - return [] - } - ) - case .float, .double: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - context.printer.write("return \(arguments[0]);") - return [] - } - ) - case .string: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - context.printer.write("const resultLen = \(arguments[0]);") - let baseFragment = stringLiftReturn - let lifted = try baseFragment.printCode([], context) - context.printer.write("return \(lifted[0]);") - return [] - } - ) - case .jsObject: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - context.printer.write("const resultId = \(arguments[0]);") - let baseFragment = jsObjectLiftReturn - let lifted = try baseFragment.printCode(["resultId"], context) - context.printer.write("return \(lifted[0]);") - return [] - } - ) - case .swiftHeapObject(let className): - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - let printer = context.printer - printer.write("const resultPtr = \(arguments[0]);") - printer.write("return _exports['\(className)'].__construct(resultPtr);") - return [] - } - ) - case .closure: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let funcRefVar = scope.variable("swiftClosureFuncRef") - printer.write("const \(funcRefVar) = \(arguments[0]);") - printer.write( - "const funcObj = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(funcRefVar));" - ) - printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(funcRefVar));") - printer.write("return funcObj;") - return [] - } - ) - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - let printer = context.printer - printer.write("const resultLen = \(arguments[0]);") - let baseFragment = stringLiftReturn - let lifted = try baseFragment.printCode([], context) - context.printer.write("return \(lifted[0]);") - return [] - } - ) - case .bool: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - let printer = context.printer - let baseFragment = boolLiftReturn - let lifted = try baseFragment.printCode([arguments[0]], context) - printer.write("return \(lifted[0]);") - return [] - } - ) - default: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - context.printer.write("return \(arguments[0]) | 0;") - return [] - } - ) - } - case .associatedValueEnum(let fullName): - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - printer.write("\(arguments[0]);") - let base = fullName.components(separatedBy: ".").last ?? fullName - let resultVar = scope.variable("result") - printer.write( - "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(scope.popTag()));" - ) - printer.write("return \(resultVar);") - return [] - } - ) - case .nullable(let wrappedType, let kind): - return try closureOptionalLiftReturn(wrappedType: wrappedType, kind: kind) - default: - throw BridgeJSLinkError(message: "Unsupported closure return type for lifting: \(type)") - } - } - - /// Handles optional return lifting for Swift closure returns - private static func closureOptionalLiftReturn( - wrappedType: BridgeType, - kind: JSOptionalKind - ) throws -> IntrinsicJSFragment { - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - let printer = context.printer - let invokeCall = arguments[0] - printer.write("\(invokeCall);") - let baseFragment = optionalLiftReturn( - wrappedType: wrappedType, - context: .importTS, - kind: kind - ) - let lifted = try baseFragment.printCode([], context) - if !lifted.isEmpty { - printer.write("return \(lifted[0]);") - } - return [] - } - ) - } - - /// Provides appropriate default values for error cases in closure invocation - static func closureErrorReturn(type: BridgeType) -> IntrinsicJSFragment { - return IntrinsicJSFragment( - parameters: [], - printCode: { arguments, context in - let printer = context.printer - switch type { - case .void: - printer.write("return;") - case .string: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnBytes) = new Uint8Array(0);") - printer.write("return 0;") - case .int, .bool, .caseEnum: - printer.write("return 0;") - case .float, .double: - printer.write("return 0.0;") - case .jsObject, .swiftHeapObject: - printer.write("return 0;") - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnBytes) = new Uint8Array(0);") - printer.write("return 0;") - case .bool, .int, .int32, .int64, .uint, .uint32, .uint64: - printer.write("return 0;") - case .float, .double: - printer.write("return 0.0;") - } - case .associatedValueEnum: - printer.write("return;") - case .nullable(let wrappedType, _): - switch wrappedType { - case .swiftHeapObject: - printer.write("return 0;") - default: - printer.write("return;") - } - default: - printer.write("return 0;") - } - - return [] - } - ) - } - // MARK: - ExportSwift /// Returns a fragment that lowers a JS value to Wasm core values for parameters diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js index 09f9aee5..2ef9aaf5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js @@ -328,337 +328,299 @@ export async function createInstantiator(options, swift) { const func = swift.memory.getObject(funcRef); func.__unregister(); } - - bjs["invoke_js_callback_TestModule_10TestModule10HttpStatusO_10HttpStatusO"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModule10HttpStatusO_10HttpStatusO"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = param0Id; - const result = callback(param0); - return result | 0; + let ret = callback(param0); + return ret; } catch (error) { - setException?.(error); - return 0; + setException(error); + return 0 } - }; + } bjs["make_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO(boxPtr, param0); + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - return invokeResult | 0; + return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO); } - - bjs["invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - const param0IdObject = swift.memory.getObject(param0Id); - swift.memory.release(param0Id); - let param0 = String(param0IdObject); - const result = callback(param0); - tmpRetBytes = textEncoder.encode(result); + const param0Object = swift.memory.getObject(param0); + swift.memory.release(param0); + let ret = callback(param0Object); + tmpRetBytes = textEncoder.encode(ret); return tmpRetBytes.length; } catch (error) { - setException?.(error); - tmpRetBytes = new Uint8Array(0); - return 0; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModule5ThemeO_5ThemeO = function(param0) { const param0Bytes = textEncoder.encode(param0); const param0Id = swift.memory.retain(param0Bytes); - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO(boxPtr, param0Id, param0Bytes.length); + instance.exports.invoke_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO(boxPtr, param0Id, param0Bytes.length); + const ret = tmpRetString; + tmpRetString = undefined; + swift.memory.release(param0Id); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - const resultLen = invokeResult; - const ret = tmpRetString; - tmpRetString = undefined; return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule5ThemeO_5ThemeO); } - - bjs["invoke_js_callback_TestModule_10TestModule6PersonC_6PersonC"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModule6PersonC_6PersonC"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = _exports['Person'].__construct(param0Id); - const result = callback(param0); - return result.pointer; + let ret = callback(_exports['Person'].__construct(param0)); + return ret.pointer; } catch (error) { - setException?.(error); - return 0; + setException(error); + return 0 } - }; + } bjs["make_swift_closure_TestModule_10TestModule6PersonC_6PersonC"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModule6PersonC_6PersonC = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule6PersonC_6PersonC(boxPtr, param0.pointer); + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModule6PersonC_6PersonC(boxPtr, param0.pointer); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - const resultPtr = invokeResult; - return _exports['Person'].__construct(resultPtr); + return _exports['Person'].__construct(ret); }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule6PersonC_6PersonC); } - - bjs["invoke_js_callback_TestModule_10TestModule9APIResultO_9APIResultO"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModule9APIResultO_9APIResultO"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = enumHelpers.APIResult.lift(param0Id); - const result = callback(param0); - const { caseId: caseId, cleanup: cleanup } = enumHelpers.APIResult.lower(result); + const enumValue = enumHelpers.APIResult.lift(param0); + let ret = callback(enumValue); + const { caseId: caseId, cleanup: cleanup } = enumHelpers.APIResult.lower(ret); return caseId; } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModule9APIResultO_9APIResultO = function(param0) { const { caseId: param0CaseId, cleanup: param0Cleanup } = enumHelpers.APIResult.lower(param0); - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO(boxPtr, param0CaseId); + instance.exports.invoke_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO(boxPtr, param0CaseId); + const ret = enumHelpers.APIResult.lift(tagStack.pop()); + if (param0Cleanup) { param0Cleanup(); } if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const result = enumHelpers.APIResult.lift(tagStack.pop()); - return result; + return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule9APIResultO_9APIResultO); } - - bjs["invoke_js_callback_TestModule_10TestModule9DirectionO_9DirectionO"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModule9DirectionO_9DirectionO"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = param0Id; - const result = callback(param0); - return result | 0; + let ret = callback(param0); + return ret; } catch (error) { - setException?.(error); - return 0; + setException(error); + return 0 } - }; + } bjs["make_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModule9DirectionO_9DirectionO = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO(boxPtr, param0); + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - return invokeResult | 0; + return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule9DirectionO_9DirectionO); } - - bjs["invoke_js_callback_TestModule_10TestModuleSS_SS"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModuleSS_SS"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - const param0IdObject = swift.memory.getObject(param0Id); - swift.memory.release(param0Id); - let param0 = String(param0IdObject); - const result = callback(param0); - if (typeof result !== "string") { - throw new TypeError("Callback must return a string"); - } - tmpRetBytes = textEncoder.encode(result); + const param0Object = swift.memory.getObject(param0); + swift.memory.release(param0); + let ret = callback(param0Object); + tmpRetBytes = textEncoder.encode(ret); return tmpRetBytes.length; } catch (error) { - setException?.(error); - tmpRetBytes = new Uint8Array(0); - return 0; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSS_SS"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSS_SS = function(param0) { const param0Bytes = textEncoder.encode(param0); const param0Id = swift.memory.retain(param0Bytes); - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSS_SS(boxPtr, param0Id, param0Bytes.length); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSS_SS(boxPtr, param0Id, param0Bytes.length); + const ret = tmpRetString; + tmpRetString = undefined; + swift.memory.release(param0Id); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - const resultLen = invokeResult; - const ret = tmpRetString; - tmpRetString = undefined; return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSS_SS); } - - bjs["invoke_js_callback_TestModule_10TestModuleSb_Sb"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModuleSb_Sb"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = param0Id !== 0; - const result = callback(param0); - return result ? 1 : 0; + let ret = callback(param0 !== 0); + return ret ? 1 : 0; } catch (error) { - setException?.(error); - return 0; + setException(error); + return 0 } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSb_Sb"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSb_Sb = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSb_Sb(boxPtr, param0); + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModuleSb_Sb(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - return invokeResult !== 0; + return ret !== 0; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSb_Sb); } - - bjs["invoke_js_callback_TestModule_10TestModuleSd_Sd"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModuleSd_Sd"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = param0Id; - const result = callback(param0); - return result; + let ret = callback(param0); + return ret; } catch (error) { - setException?.(error); - return 0.0; + setException(error); + return 0 } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSd_Sd"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSd_Sd = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSd_Sd(boxPtr, param0); + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModuleSd_Sd(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - return invokeResult; + return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSd_Sd); } - - bjs["invoke_js_callback_TestModule_10TestModuleSf_Sf"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModuleSf_Sf"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = param0Id; - const result = callback(param0); - return Math.fround(result); + let ret = callback(param0); + return ret; } catch (error) { - setException?.(error); - return 0.0; + setException(error); + return 0 } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSf_Sf"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSf_Sf = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSf_Sf(boxPtr, param0); + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModuleSf_Sf(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - return invokeResult; + return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSf_Sf); } - - bjs["invoke_js_callback_TestModule_10TestModuleSi_Si"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModuleSi_Si"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = param0Id; - const result = callback(param0); - return result | 0; + let ret = callback(param0); + return ret; } catch (error) { - setException?.(error); - return 0; + setException(error); + return 0 } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSi_Si"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSi_Si = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSi_Si(boxPtr, param0); + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModuleSi_Si(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - return invokeResult | 0; + return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSi_Si); } - - bjs["invoke_js_callback_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; - if (param0IsSome) { - param0 = param0Value; - } else { - param0 = null; - } - const result = callback(param0); - tmpRetOptionalInt = result; - return; + let ret = callback(param0IsSome ? param0WrappedValue : null); + const isSome = ret != null; + bjs["swift_js_return_optional_int"](isSome ? 1 : 0, isSome ? (ret | 0) : 0); } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO = function(param0) { const isSome = param0 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(boxPtr, +isSome, isSome ? param0 : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const optResult = tmpRetOptionalInt; - tmpRetOptionalInt = undefined; return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO); } - - bjs["invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; + let obj; if (param0IsSome) { - const param0Object = swift.memory.getObject(param0Value); - swift.memory.release(param0Value); - param0 = String(param0Object); + obj = swift.memory.getObject(param0WrappedValue); + swift.memory.release(param0WrappedValue); + } + let ret = callback(param0IsSome ? obj : null); + const isSome = ret != null; + if (isSome) { + tmpRetString = ret; } else { - param0 = null; + tmpRetString = null; } - const result = callback(param0); - tmpRetString = result; - return; } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO = function(param0) { const isSome = param0 != null; @@ -667,78 +629,68 @@ export async function createInstantiator(options, swift) { param0Bytes = textEncoder.encode(param0); param0Id = swift.memory.retain(param0Bytes); } - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(boxPtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(boxPtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + if (param0Id != undefined) { + swift.memory.release(param0Id); + } if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const optResult = tmpRetString; - tmpRetString = undefined; return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO); } - - bjs["invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; - if (param0IsSome) { - param0 = _exports['Person'].__construct(param0Value); - } else { - param0 = null; - } - const result = callback(param0); - return result ? result.pointer : 0; + let ret = callback(param0IsSome ? _exports['Person'].__construct(param0WrappedValue) : null); + const isSome = ret != null; + return isSome ? ret.pointer : 0; } catch (error) { - setException?.(error); - return 0; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC = function(param0) { const isSome = param0 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC(boxPtr, +isSome, isSome ? param0.pointer : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC(boxPtr, +isSome, isSome ? param0.pointer : 0); + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + const optResult = pointer === null ? null : _exports['Person'].__construct(pointer); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const pointer = tmpRetOptionalHeapObject; - tmpRetOptionalHeapObject = undefined; - const optResult = pointer === null ? null : _exports['Person'].__construct(pointer); return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC); } - - bjs["invoke_js_callback_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; + let enumValue; if (param0IsSome) { - param0 = enumHelpers.APIResult.lift(param0Value); - } else { - param0 = null; + enumValue = enumHelpers.APIResult.lift(param0WrappedValue); } - const result = callback(param0); - if (result) { - const { caseId: caseId, cleanup: cleanup } = enumHelpers.APIResult.lower(result); - tmpRetOptionalInt = caseId; + let ret = callback(param0IsSome ? enumValue : null); + const isSome = ret != null; + if (isSome) { + const { caseId: caseId, cleanup: cleanup } = enumHelpers.APIResult.lower(ret); + return caseId; } else { - tmpRetOptionalInt = null; + return -1; } - return; } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO = function(param0) { const isSome = param0 != null; @@ -748,14 +700,7 @@ export async function createInstantiator(options, swift) { param0CaseId = enumResult.caseId; param0Cleanup = enumResult.cleanup; } - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(boxPtr, +isSome, isSome ? param0CaseId : 0); - if (tmpRetException) { - const error = swift.memory.getObject(tmpRetException); - swift.memory.release(tmpRetException); - tmpRetException = undefined; - throw error; - } - invokeResult; + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(boxPtr, +isSome, isSome ? param0CaseId : 0); const tag = tagStack.pop(); const isNull = (tag === -1); let optResult; @@ -764,65 +709,62 @@ export async function createInstantiator(options, swift) { } else { optResult = enumHelpers.APIResult.lift(tag); } + if (param0Cleanup) { param0Cleanup(); } + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO); } - - bjs["invoke_js_callback_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; - if (param0IsSome) { - param0 = param0Value; - } else { - param0 = null; - } - const result = callback(param0); - tmpRetOptionalInt = result; - return; + let ret = callback(param0IsSome ? param0WrappedValue : null); + const isSome = ret != null; + return isSome ? (ret | 0) : -1; } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO = function(param0) { const isSome = param0 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(boxPtr, +isSome, isSome ? param0 : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const optResult = tmpRetOptionalInt; - tmpRetOptionalInt = undefined; return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO); } - - bjs["invoke_js_callback_TestModule_10TestModuleSqSS_SqSS"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSqSS_SqSS"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; + let obj; if (param0IsSome) { - const param0Object = swift.memory.getObject(param0Value); - swift.memory.release(param0Value); - param0 = String(param0Object); + obj = swift.memory.getObject(param0WrappedValue); + swift.memory.release(param0WrappedValue); + } + let ret = callback(param0IsSome ? obj : null); + const isSome = ret != null; + if (isSome) { + tmpRetString = ret; } else { - param0 = null; + tmpRetString = null; } - const result = callback(param0); - tmpRetString = result; - return; } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSqSS_SqSS"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSqSS_SqSS = function(param0) { const isSome = param0 != null; @@ -831,156 +773,122 @@ export async function createInstantiator(options, swift) { param0Bytes = textEncoder.encode(param0); param0Id = swift.memory.retain(param0Bytes); } - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSS_SqSS(boxPtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSS_SqSS(boxPtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + if (param0Id != undefined) { + swift.memory.release(param0Id); + } if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const optResult = tmpRetString; - tmpRetString = undefined; return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSS_SqSS); } - - bjs["invoke_js_callback_TestModule_10TestModuleSqSb_SqSb"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSqSb_SqSb"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; - if (param0IsSome) { - param0 = param0Value !== 0; - } else { - param0 = null; - } - const result = callback(param0); - tmpRetOptionalBool = result; - return; + let ret = callback(param0IsSome ? param0WrappedValue !== 0 : null); + const isSome = ret != null; + bjs["swift_js_return_optional_bool"](isSome ? 1 : 0, isSome ? (ret ? 1 : 0) : 0); } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSqSb_SqSb"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSqSb_SqSb = function(param0) { const isSome = param0 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSb_SqSb(boxPtr, +isSome, isSome ? param0 : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSb_SqSb(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalBool; + tmpRetOptionalBool = undefined; if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const optResult = tmpRetOptionalBool; - tmpRetOptionalBool = undefined; return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSb_SqSb); } - - bjs["invoke_js_callback_TestModule_10TestModuleSqSd_SqSd"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSqSd_SqSd"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; - if (param0IsSome) { - param0 = param0Value; - } else { - param0 = null; - } - const result = callback(param0); - tmpRetOptionalDouble = result; - return; + let ret = callback(param0IsSome ? param0WrappedValue : null); + const isSome = ret != null; + bjs["swift_js_return_optional_double"](isSome ? 1 : 0, isSome ? ret : 0.0); } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSqSd_SqSd"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSqSd_SqSd = function(param0) { const isSome = param0 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSd_SqSd(boxPtr, +isSome, isSome ? param0 : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSd_SqSd(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const optResult = tmpRetOptionalDouble; - tmpRetOptionalDouble = undefined; return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSd_SqSd); } - - bjs["invoke_js_callback_TestModule_10TestModuleSqSf_SqSf"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSqSf_SqSf"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; - if (param0IsSome) { - param0 = Math.fround(param0Value); - } else { - param0 = null; - } - const result = callback(param0); - tmpRetOptionalFloat = result; - return; + let ret = callback(param0IsSome ? param0WrappedValue : null); + const isSome = ret != null; + bjs["swift_js_return_optional_float"](isSome ? 1 : 0, isSome ? Math.fround(ret) : 0.0); } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSqSf_SqSf"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSqSf_SqSf = function(param0) { const isSome = param0 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSf_SqSf(boxPtr, +isSome, isSome ? param0 : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSf_SqSf(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const optResult = tmpRetOptionalFloat; - tmpRetOptionalFloat = undefined; return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSf_SqSf); } - - bjs["invoke_js_callback_TestModule_10TestModuleSqSi_SqSi"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSqSi_SqSi"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; - if (param0IsSome) { - param0 = param0Value | 0; - } else { - param0 = null; - } - const result = callback(param0); - tmpRetOptionalInt = result; - return; + let ret = callback(param0IsSome ? param0WrappedValue : null); + const isSome = ret != null; + bjs["swift_js_return_optional_int"](isSome ? 1 : 0, isSome ? (ret | 0) : 0); } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSqSi_SqSi"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSqSi_SqSi = function(param0) { const isSome = param0 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSi_SqSi(boxPtr, +isSome, isSome ? param0 : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSi_SqSi(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const optResult = tmpRetOptionalInt; - tmpRetOptionalInt = undefined; return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSi_SqSi); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js index 57b34d42..98899d4d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js @@ -228,28 +228,26 @@ export async function createInstantiator(options, swift) { const func = swift.memory.getObject(funcRef); func.__unregister(); } - - bjs["invoke_js_callback_TestModule_10TestModuleSi_Si"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModuleSi_Si"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = param0Id; - const result = callback(param0); - return result | 0; + let ret = callback(param0); + return ret; } catch (error) { - setException?.(error); - return 0; + setException(error); + return 0 } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSi_Si"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSi_Si = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSi_Si(boxPtr, param0); + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModuleSi_Si(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - return invokeResult | 0; + return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSi_Si); }