From 0919be8486e0b4d0e66caa4e2b2d099f55a805f2 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Wed, 4 Feb 2026 15:57:46 +0900 Subject: [PATCH] BridgeJS: Add `JSTypedClosure` API The new API allows managing JS closures converted from Swift closures from Swift side. It allows us to get the underlying `JSObject` and manage its lifetime manually from Swift. ```swift @JS func makeIntToInt() throws(JSException) -> JSTypedClosure<(Int) -> Int> { return JSTypedClosure { x in return x + 1 } } @JSFunction func takeIntToInt(_ transform: JSTypedClosure<(Int) -> Int>) throws(JSException) let closure = JSTypedClosure<(Int) -> Int> { x in return x * 2 } defer { closure.release() } try takeIntToInt(closure) ``` Likewise to `JSClosure`, API users are responsible for "manually" releasing the closure when it's no longer needed by calling `release()`. After releasing, the closure becomes unusable and calling it will throw a JS exception (note that we will not segfault even if the closure is called after releasing). ```swift let closure = JSTypedClosure<(Int) -> Int> { x in return x * 2 } closure.release() try closure(10) // "JSException: Attempted to call a released JSTypedClosure created at :" ``` As a belt-and-suspenders measure, the underlying JS closure is also registered with a `FinalizationRegistry` to ensure that the Swift closure box is released when the JS closure is garbage collected, in case the API user forgets to call `release()`. However, relying on this mechanism is **not recommended** because the timing of garbage collection is non-deterministic and it's not guaranteed that it will happen in a timely manner. ---- On the top of the new API, this commit also fixes memory leak issues of closures exported to JS. --- Package.swift | 15 +- Package@swift-6.2.swift | 15 +- .../Sources/BridgeJSCore/ClosureCodegen.swift | 81 +- .../Sources/BridgeJSCore/ExportSwift.swift | 27 +- .../Sources/BridgeJSCore/ImportTS.swift | 61 +- .../BridgeJSCore/SwiftToSkeleton.swift | 31 +- .../Sources/BridgeJSLink/BridgeJSLink.swift | 188 +- .../Sources/BridgeJSLink/JSGlueGen.swift | 44 +- .../BridgeJSSkeleton/BridgeJSSkeleton.swift | 19 +- .../BridgeJSCodegenTests/SwiftClosure.json | 60 +- .../BridgeJSCodegenTests/SwiftClosure.swift | 435 ++-- .../SwiftClosureImports.json | 6 +- .../SwiftClosureImports.swift | 42 +- .../BridgeJSLinkTests/SwiftClosure.js | 399 ++-- .../BridgeJSLinkTests/SwiftClosureImports.js | 49 +- Plugins/PackageToJS/Templates/instantiate.js | 1 + .../JavaScriptKit/BridgeJSIntrinsics.swift | 49 + .../FundamentalObjects/JSClosure.swift | 91 + .../ClosureSupportTests.swift | 290 +++ .../Generated/BridgeJS.swift | 1769 ++++++++++++----- .../Generated/JavaScript/BridgeJS.json | 1527 ++++++++++---- .../BridgeJSRuntimeTests/ImportAPITests.swift | 30 - .../ImportClosureAPIs.swift | 11 - .../JavaScript/ClosureSupportTests.mjs | 311 +++ .../JavaScriptKitTests.swift | 4 + Tests/prelude.mjs | 215 +- 26 files changed, 4105 insertions(+), 1665 deletions(-) create mode 100644 Tests/BridgeJSRuntimeTests/ClosureSupportTests.swift delete mode 100644 Tests/BridgeJSRuntimeTests/ImportClosureAPIs.swift create mode 100644 Tests/BridgeJSRuntimeTests/JavaScript/ClosureSupportTests.mjs diff --git a/Package.swift b/Package.swift index c7f3517e..60adb7a5 100644 --- a/Package.swift +++ b/Package.swift @@ -9,12 +9,15 @@ let useLegacyResourceBundling = Context.environment["JAVASCRIPTKIT_USE_LEGACY_RESOURCE_BUNDLING"].flatMap(Bool.init) ?? false let testingLinkerFlags: [LinkerSetting] = [ - .unsafeFlags([ - "-Xlinker", "--stack-first", - "-Xlinker", "--global-base=524288", - "-Xlinker", "-z", - "-Xlinker", "stack-size=524288", - ]) + .unsafeFlags( + [ + "-Xlinker", "--stack-first", + "-Xlinker", "--global-base=524288", + "-Xlinker", "-z", + "-Xlinker", "stack-size=524288", + ], + .when(platforms: [.wasi]) + ) ] let package = Package( diff --git a/Package@swift-6.2.swift b/Package@swift-6.2.swift index f640feeb..20583865 100644 --- a/Package@swift-6.2.swift +++ b/Package@swift-6.2.swift @@ -16,12 +16,15 @@ let tracingTrait = Trait( ) let testingLinkerFlags: [LinkerSetting] = [ - .unsafeFlags([ - "-Xlinker", "--stack-first", - "-Xlinker", "--global-base=524288", - "-Xlinker", "-z", - "-Xlinker", "stack-size=524288", - ]) + .unsafeFlags( + [ + "-Xlinker", "--stack-first", + "-Xlinker", "--global-base=524288", + "-Xlinker", "-z", + "-Xlinker", "stack-size=524288", + ], + .when(platforms: [.wasi]) + ) ] let package = Package( diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift index 30cf8b2c..12e4a413 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift @@ -16,7 +16,7 @@ public struct ClosureCodegen { func collectClosureSignatures(from type: BridgeType, into signatures: inout Set) { switch type { - case .closure(let signature): + case .closure(let signature, _): signatures.insert(signature) for paramType in signature.parameters { collectClosureSignatures(from: paramType, into: &signatures) @@ -32,7 +32,6 @@ public struct ClosureCodegen { func renderClosureHelpers(_ signature: ClosureSignature) throws -> [DeclSyntax] { let mangledName = signature.mangleName let helperName = "_BJS_Closure_\(mangledName)" - let boxClassName = "_BJS_ClosureBox_\(mangledName)" let closureParams = signature.parameters.enumerated().map { _, type in "\(type.swiftType)" @@ -40,7 +39,7 @@ public struct ClosureCodegen { let swiftEffects = (signature.isAsync ? " async" : "") + (signature.isThrows ? " throws" : "") let swiftReturnType = signature.returnType.swiftType - let closureType = "(\(closureParams))\(swiftEffects) -> \(swiftReturnType)" + let swiftClosureType = "(\(closureParams))\(swiftEffects) -> \(swiftReturnType)" let externName = "invoke_js_callback_\(signature.moduleName)_\(mangledName)" @@ -69,13 +68,15 @@ public struct ClosureCodegen { // Generate extern declaration using CallJSEmission let externDecl = builder.renderImportDecl() - let boxClassDecl: DeclSyntax = """ - private final class \(raw: boxClassName): _BridgedSwiftClosureBox { - let closure: \(raw: closureType) - init(_ closure: @escaping \(raw: closureType)) { - self.closure = closure - } + let makeClosureExternDecl: DeclSyntax = """ + #if arch(wasm32) + @_extern(wasm, module: "bjs", name: "make_swift_closure_\(raw: signature.moduleName)_\(raw: signature.mangleName)") + fileprivate func make_swift_closure_\(raw: signature.moduleName)_\(raw: signature.mangleName)(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 + #else + fileprivate func make_swift_closure_\(raw: signature.moduleName)_\(raw: signature.mangleName)(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } + #endif """ let helperEnumDecl = EnumDeclSyntax( @@ -84,33 +85,6 @@ public struct ClosureCodegen { }, name: .identifier(helperName), memberBlockBuilder: { - DeclSyntax( - FunctionDeclSyntax( - modifiers: DeclModifierListSyntax { - DeclModifierSyntax(name: .keyword(.static)) - }, - name: .identifier("bridgeJSLower"), - signature: FunctionSignatureSyntax( - parameterClause: FunctionParameterClauseSyntax { - FunctionParameterSyntax( - firstName: .wildcardToken(), - secondName: .identifier("closure"), - colon: .colonToken(), - type: TypeSyntax("@escaping \(raw: closureType)") - ) - }, - returnClause: ReturnClauseSyntax( - arrow: .arrowToken(), - type: IdentifierTypeSyntax(name: .identifier("UnsafeMutableRawPointer")) - ) - ), - body: CodeBlockSyntax { - "let box = \(raw: boxClassName)(closure)" - "return Unmanaged.passRetained(box).toOpaque()" - } - ) - ) - DeclSyntax( FunctionDeclSyntax( modifiers: DeclModifierListSyntax { @@ -128,7 +102,7 @@ public struct ClosureCodegen { }, returnClause: ReturnClauseSyntax( arrow: .arrowToken(), - type: IdentifierTypeSyntax(name: .identifier(closureType)) + type: IdentifierTypeSyntax(name: .identifier(swiftClosureType)) ) ), body: CodeBlockSyntax { @@ -178,11 +152,32 @@ public struct ClosureCodegen { ) } ) - return [externDecl, boxClassDecl, DeclSyntax(helperEnumDecl)] + let typedClosureExtension: DeclSyntax = """ + extension JSTypedClosure where Signature == \(raw: swiftClosureType) { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping \(raw: swiftClosureType)) { + self.init( + makeClosure: make_swift_closure_\(raw: signature.moduleName)_\(raw: signature.mangleName), + body: body, + fileID: fileID, + line: line + ) + } + } + """ + + return [ + externDecl, makeClosureExternDecl, DeclSyntax(helperEnumDecl), typedClosureExtension, + ] } func renderClosureInvokeHandler(_ signature: ClosureSignature) throws -> DeclSyntax { - let boxClassName = "_BJS_ClosureBox_\(signature.mangleName)" + let closureParams = signature.parameters.enumerated().map { _, type in + "\(type.swiftType)" + }.joined(separator: ", ") + let swiftEffects = (signature.isAsync ? " async" : "") + (signature.isThrows ? " throws" : "") + let swiftReturnType = signature.returnType.swiftType + let swiftClosureType = "(\(closureParams))\(swiftEffects) -> \(swiftReturnType)" + let boxType = "_BridgeJSTypedClosureBox<\(swiftClosureType)>" let abiName = "invoke_swift_closure_\(signature.moduleName)_\(signature.mangleName)" // Build ABI parameters directly with WasmCoreType (no string conversion needed) @@ -205,7 +200,7 @@ public struct ClosureCodegen { liftedParams.append("\(paramType.swiftType).bridgeJSLiftParameter(\(argNames.joined(separator: ", ")))") } - let closureCallExpr = ExprSyntax("box.closure(\(raw: liftedParams.joined(separator: ", ")))") + let closureCallExpr = ExprSyntax("closure(\(raw: liftedParams.joined(separator: ", ")))") // Determine return type let abiReturnWasmType: WasmCoreType? @@ -217,6 +212,8 @@ public struct ClosureCodegen { abiReturnWasmType = nil } + let throwReturn = abiReturnWasmType?.swiftReturnPlaceholderStmt ?? "return" + // Build signature using SwiftSignatureBuilder let funcSignature = SwiftSignatureBuilder.buildABIFunctionSignature( abiParameters: abiParams, @@ -225,7 +222,7 @@ public struct ClosureCodegen { // Build body let body = CodeBlockItemListSyntax { - "let box = Unmanaged<\(raw: boxClassName)>.fromOpaque(boxPtr).takeUnretainedValue()" + "let closure = Unmanaged<\(raw: boxType)>.fromOpaque(boxPtr).takeUnretainedValue().closure" if signature.returnType == .void { closureCallExpr } else { @@ -315,7 +312,7 @@ public struct ClosureCodegen { for setter in type.setters { collectClosureSignatures(from: setter.type, into: &closureSignatures) } - for method in type.methods { + for method in type.methods + type.staticMethods { collectClosureSignatures(from: method.parameters, into: &closureSignatures) collectClosureSignatures(from: method.returnType, into: &closureSignatures) } diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index aa01a2c5..acff2184 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -124,7 +124,7 @@ public class ExportSwift { let liftingExpr: ExprSyntax switch param.type { - case .closure(let signature): + case .closure(let signature, _): typeNameForIntrinsic = param.type.swiftType liftingExpr = ExprSyntax("_BJS_Closure_\(raw: signature.mangleName).bridgeJSLift(\(raw: param.name))") case .swiftStruct(let structName): @@ -364,8 +364,8 @@ public class ExportSwift { } switch returnType { - case .closure(let signature): - append("return _BJS_Closure_\(raw: signature.mangleName).bridgeJSLower(ret)") + case .closure(_, useJSTypedClosure: false): + append("return JSTypedClosure(ret).bridgeJSLowerReturn()") case .array, .nullable(.array, _): let stackCodegen = StackCodegen() for stmt in stackCodegen.lowerStatements(for: returnType, accessor: "ret", varPrefix: "ret") { @@ -423,14 +423,7 @@ public class ExportSwift { } private func returnPlaceholderStmt() -> String { - switch abiReturnType { - case .i32: return "return 0" - case .i64: return "return 0" - case .f32: return "return 0.0" - case .f64: return "return 0.0" - case .pointer: return "return UnsafeMutableRawPointer(bitPattern: -1).unsafelyUnwrapped" - case .none: return "return" - } + return abiReturnType?.swiftReturnPlaceholderStmt ?? "return" } } @@ -1749,13 +1742,19 @@ extension BridgeType { case .associatedValueEnum(let name): return name case .swiftStruct(let name): return name case .namespaceEnum(let name): return name - case .closure(let signature): + case .closure(let signature, let useJSTypedClosure): let paramTypes = signature.parameters.map { $0.swiftType }.joined(separator: ", ") let effectsStr = (signature.isAsync ? " async" : "") + (signature.isThrows ? " throws" : "") - return "(\(paramTypes))\(effectsStr) -> \(signature.returnType.swiftType)" + let closureType = "(\(paramTypes))\(effectsStr) -> \(signature.returnType.swiftType)" + return useJSTypedClosure ? "JSTypedClosure<\(closureType)>" : closureType } } + var isClosureType: Bool { + if case .closure = self { return true } + return false + } + struct LiftingIntrinsicInfo: Sendable { let parameters: [(name: String, type: WasmCoreType)] @@ -1853,7 +1852,7 @@ extension BridgeType { case .namespaceEnum: throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters") case .closure: - return .swiftHeapObject + return .jsObject case .array, .dictionary: return .array } diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift index 7c3ecd6e..0424d8ca 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift @@ -85,6 +85,8 @@ public struct ImportTS { var destructuredVarNames: [String] = [] // Stack-lowered parameters should be evaluated in reverse order to match LIFO stacks var stackLoweringStmts: [CodeBlockItemSyntax] = [] + // Values to extend lifetime during call + var valuesToExtendLifetimeDuringCall: [ExprSyntax] = [] init(moduleName: String, abiName: String, context: BridgeContext = .importTS) { self.moduleName = moduleName @@ -95,15 +97,17 @@ public struct ImportTS { func lowerParameter(param: Parameter) throws { let loweringInfo = try param.type.loweringParameterInfo(context: context) - let initializerExpr: ExprSyntax switch param.type { - case .closure(let signature): - initializerExpr = ExprSyntax( - "_BJS_Closure_\(raw: signature.mangleName).bridgeJSLower(\(raw: param.name))" - ) + case .closure(let signature, useJSTypedClosure: false): + let jsTypedClosureType = BridgeType.closure(signature, useJSTypedClosure: true).swiftType + body.append("let \(raw: param.name) = \(raw: jsTypedClosureType)(\(raw: param.name))") + // The just created JSObject is not owned by the caller unlike those passed in parameters, + // so we need to extend its lifetime during the call to ensure the JSObject.id is valid. + valuesToExtendLifetimeDuringCall.append("\(raw: param.name)") default: - initializerExpr = ExprSyntax("\(raw: param.name).bridgeJSLowerParameter()") + break } + let initializerExpr = ExprSyntax("\(raw: param.name).bridgeJSLowerParameter()") if loweringInfo.loweredParameters.isEmpty { let stmt = CodeBlockItemSyntax( @@ -193,7 +197,7 @@ public struct ImportTS { let liftingInfo = try returnType.liftingReturnInfo(context: context) body.append(contentsOf: stackLoweringStmts) - let callExpr = FunctionCallExprSyntax( + var callExpr = FunctionCallExprSyntax( calledExpression: ExprSyntax("\(raw: abiName)"), leftParen: .leftParenToken(), arguments: LabeledExprListSyntax { @@ -204,12 +208,33 @@ public struct ImportTS { rightParen: .rightParenToken() ) - if returnType == .void { - body.append(CodeBlockItemSyntax(item: .stmt(StmtSyntax(ExpressionStmtSyntax(expression: callExpr))))) - } else if returnType.usesSideChannelForOptionalReturn() { - // Side channel returns don't need "let ret =" - body.append(CodeBlockItemSyntax(item: .stmt(StmtSyntax(ExpressionStmtSyntax(expression: callExpr))))) - } else if liftingInfo.valueToLift == nil { + if !valuesToExtendLifetimeDuringCall.isEmpty { + callExpr = FunctionCallExprSyntax( + calledExpression: ExprSyntax("withExtendedLifetime"), + leftParen: .leftParenToken(), + arguments: LabeledExprListSyntax { + LabeledExprSyntax( + expression: TupleExprSyntax( + elements: LabeledExprListSyntax { + for value in valuesToExtendLifetimeDuringCall { + LabeledExprSyntax(expression: value) + } + } + ) + ) + }, + rightParen: .rightParenToken(), + trailingClosure: ClosureExprSyntax( + leftBrace: .leftBraceToken(), + statements: CodeBlockItemListSyntax { + CodeBlockItemSyntax(item: .stmt(StmtSyntax(ExpressionStmtSyntax(expression: callExpr)))) + }, + rightBrace: .rightBraceToken() + ) + ) + } + + if returnType == .void || returnType.usesSideChannelForOptionalReturn() || liftingInfo.valueToLift == nil { body.append(CodeBlockItemSyntax(item: .stmt(StmtSyntax(ExpressionStmtSyntax(expression: callExpr))))) } else { body.append("let ret = \(raw: callExpr)") @@ -249,7 +274,7 @@ public struct ImportTS { abiReturnType = liftingInfo.valueToLift let liftExpr: ExprSyntax switch returnType { - case .closure(let signature): + case .closure(let signature, _): liftExpr = ExprSyntax("_BJS_Closure_\(raw: signature.mangleName).bridgeJSLift(ret)") default: if liftingInfo.valueToLift != nil { @@ -722,11 +747,9 @@ struct SwiftSignatureBuilder { } /// Builds a parameter type syntax from a BridgeType. - /// - /// Swift closure parameters must be `@escaping` because they are boxed and can be invoked from JavaScript. static func buildParameterTypeSyntax(from type: BridgeType) -> TypeSyntax { switch type { - case .closure: + case .closure(_, useJSTypedClosure: false): return TypeSyntax("@escaping \(raw: type.swiftType)") default: return buildTypeSyntax(from: type) @@ -930,8 +953,8 @@ extension BridgeType { case .jsValue: return .jsValue case .void: return .void case .closure: - // Swift closure is boxed and passed to JS as a pointer. - return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)]) + // Swift closure is passed to JS as a JS function reference. + return LoweringParameterInfo(loweredParameters: [("funcRef", .i32)]) case .unsafePointer: return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)]) case .swiftHeapObject(let className): diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift index e571d955..1d775fbc 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift @@ -100,6 +100,17 @@ public final class SwiftToSkeleton { return lookupType(for: attributedType.baseType, errors: &errors) } + if let identifierType = type.as(IdentifierTypeSyntax.self), + identifierType.name.text == "JSTypedClosure", + let genericArgs = identifierType.genericArgumentClause?.arguments, + genericArgs.count == 1, + let argument = genericArgs.firstAsTypeSyntax, + let signatureType = lookupType(for: argument, errors: &errors), + case .closure(let signature, false) = signatureType + { + return .closure(signature, useJSTypedClosure: true) + } + // (T1, T2, ...) -> R if let functionType = type.as(FunctionTypeSyntax.self) { var parameters: [BridgeType] = [] @@ -124,7 +135,8 @@ public final class SwiftToSkeleton { moduleName: moduleName, isAsync: isAsync, isThrows: isThrows - ) + ), + useJSTypedClosure: false ) } @@ -889,7 +901,7 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { guard let type = resolvedType else { continue // Skip unsupported types } - if case .closure(let signature) = type { + if case .closure(let signature, _) = type { if signature.isAsync { diagnose( node: param.type, @@ -2537,3 +2549,18 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { } } } + +extension GenericArgumentListSyntax { + /// Compatibility helper for accessing the first argument as a TypeSyntax + /// + /// Note: SwiftSyntax 601 and later support InlineArrayTypeSyntax and + /// ``GenericArgumentSyntax/argument`` is now a ``TypeSyntax`` or ``ExprSyntax``. + fileprivate var firstAsTypeSyntax: TypeSyntax? { + guard let first = self.first else { return nil } + #if canImport(SwiftSyntax601) + return first.argument.as(TypeSyntax.self) + #else + return TypeSyntax(first.argument) + #endif + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index e77bfd87..1be1f496 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -261,46 +261,6 @@ public struct BridgeJSLink { ] } - /// Checks if a skeleton contains any closure types - private func hasClosureTypes(in skeleton: ExportedSkeleton) -> Bool { - for function in skeleton.functions { - if containsClosureType(in: function.parameters) || containsClosureType(in: function.returnType) { - return true - } - } - for klass in skeleton.classes { - if let constructor = klass.constructor, containsClosureType(in: constructor.parameters) { - return true - } - for method in klass.methods { - if containsClosureType(in: method.parameters) || containsClosureType(in: method.returnType) { - return true - } - } - for property in klass.properties { - if containsClosureType(in: property.type) { - return true - } - } - } - return false - } - - private func containsClosureType(in parameters: [Parameter]) -> Bool { - parameters.contains { containsClosureType(in: $0.type) } - } - - private func containsClosureType(in type: BridgeType) -> Bool { - switch type { - case .closure: - return true - case .nullable(let wrapped, _): - return containsClosureType(in: wrapped) - default: - return false - } - } - private func generateAddImports(needsImportsObject: Bool) -> CodeFragmentPrinter { let printer = CodeFragmentPrinter() let allStructs = skeletons.compactMap { $0.exported?.structs }.flatMap { $0 } @@ -655,6 +615,71 @@ public struct BridgeJSLink { guard !closureSignatures.isEmpty else { continue } + intrinsicRegistry.register(name: "swiftClosureHelpers") { helperPrinter in + helperPrinter.write( + "const \(JSGlueVariableScope.reservedSwiftClosureRegistry) = (typeof FinalizationRegistry === \"undefined\") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => {" + ) + helperPrinter.indent { + helperPrinter.write("if (state.unregistered) { return; }") + helperPrinter.write( + "\(JSGlueVariableScope.reservedInstance)?.exports?.bjs_release_swift_closure(state.pointer);" + ) + } + helperPrinter.write("});") + helperPrinter.write( + "const \(JSGlueVariableScope.reservedMakeSwiftClosure) = (pointer, file, line, func) => {" + ) + helperPrinter.indent { + helperPrinter.write( + "const state = { pointer, file, line, unregistered: false };" + ) + helperPrinter.write("const real = (...args) => {") + helperPrinter.indent { + helperPrinter.write("if (state.unregistered) {") + helperPrinter.indent { + helperPrinter.write( + "const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, state.file);" + ) + helperPrinter.write("let length = 0;") + helperPrinter.write("while (bytes[length] !== 0) { length += 1; }") + helperPrinter.write( + "const fileID = \(JSGlueVariableScope.reservedTextDecoder).decode(bytes.subarray(0, length));" + ) + helperPrinter.write( + "throw new Error(`Attempted to call a released JSTypedClosure created at ${fileID}:${state.line}`);" + ) + } + helperPrinter.write("}") + helperPrinter.write("return func(...args);") + } + helperPrinter.write("};") + helperPrinter.write( + "real.__unregister = () => {" + ) + helperPrinter.indent { + helperPrinter.write( + "if (state.unregistered) { return; }" + ) + helperPrinter.write("state.unregistered = true;") + helperPrinter.write( + "\(JSGlueVariableScope.reservedSwiftClosureRegistry).unregister(state);" + ) + } + helperPrinter.write("};") + helperPrinter.write( + "\(JSGlueVariableScope.reservedSwiftClosureRegistry).register(real, state, state);" + ) + helperPrinter.write("return \(JSGlueVariableScope.reservedSwift).memory.retain(real);") + } + helperPrinter.write("};") + } + printer.write("bjs[\"swift_js_closure_unregister\"] = function(funcRef) {") + printer.indent { + printer.write("const func = \(JSGlueVariableScope.reservedSwift).memory.getObject(funcRef);") + printer.write("func.__unregister();") + } + printer.write("}") + for signature in closureSignatures.sorted(by: { $0.mangleName < $1.mangleName }) { let invokeFuncName = "invoke_js_callback_\(moduleName)_\(signature.mangleName)" printer.write( @@ -665,12 +690,17 @@ public struct BridgeJSLink { ) let lowerFuncName = "lower_closure_\(moduleName)_\(signature.mangleName)" - printer.write( - lines: generateLowerClosureFunction( - signature: signature, - functionName: lowerFuncName + let makeFuncName = "make_swift_closure_\(moduleName)_\(signature.mangleName)" + printer.write("bjs[\"\(makeFuncName)\"] = function(boxPtr, file, line) {") + printer.indent { + printer.write( + lines: generateLowerClosureFunction(signature: signature, functionName: lowerFuncName) ) - ) + printer.write( + "return \(JSGlueVariableScope.reservedMakeSwiftClosure)(boxPtr, file, line, \(lowerFuncName));" + ) + } + printer.write("}") } } } @@ -721,7 +751,7 @@ public struct BridgeJSLink { for setter in type.setters { collectClosureSignatures(from: setter.type, into: &signatures) } - for method in type.methods { + for method in type.methods + type.staticMethods { collectClosureSignatures(from: method.parameters, into: &signatures) collectClosureSignatures(from: method.returnType, into: &signatures) } @@ -737,7 +767,7 @@ public struct BridgeJSLink { private func collectClosureSignatures(from type: BridgeType, into signatures: inout Set) { switch type { - case .closure(let signature): + case .closure(let signature, _): signatures.insert(signature) for paramType in signature.parameters { collectClosureSignatures(from: paramType, into: &signatures) @@ -827,44 +857,40 @@ public struct BridgeJSLink { let scope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) let cleanupCode = CodeFragmentPrinter() - printer.nextLine() - printer.write("bjs[\"\(functionName)\"] = function(closurePtr) {") + printer.write( + "const \(functionName) = function(\(signature.parameters.indices.map { "param\($0)" }.joined(separator: ", "))) {" + ) printer.indent { - printer.write( - "return function(\(signature.parameters.indices.map { "param\($0)" }.joined(separator: ", "))) {" - ) - printer.indent { - printer.write("try {") - printer.indent { - var invokeArgs: [String] = ["closurePtr"] + var invokeArgs: [String] = ["boxPtr"] - for (index, paramType) in signature.parameters.enumerated() { - let paramName = "param\(index)" - let fragment = try! IntrinsicJSFragment.lowerParameter(type: paramType) - let lowered = fragment.printCode([paramName], scope, printer, cleanupCode) - invokeArgs.append(contentsOf: lowered) - } + for (index, paramType) in signature.parameters.enumerated() { + let paramName = "param\(index)" + let fragment = try! IntrinsicJSFragment.lowerParameter(type: paramType) + let lowered = fragment.printCode([paramName], scope, printer, cleanupCode) + invokeArgs.append(contentsOf: lowered) + } - // Call the Swift invoke function - let invokeCall = - "\(JSGlueVariableScope.reservedInstance).exports.invoke_swift_closure_\(signature.moduleName)_\(signature.mangleName)(\(invokeArgs.joined(separator: ", ")))" + // 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);") - let returnFragment = try! IntrinsicJSFragment.closureLiftReturn(type: signature.returnType) - _ = returnFragment.printCode([invokeCall], scope, printer, cleanupCode) - } - printer.write("} catch (error) {") - printer.indent { - printer.write("\(JSGlueVariableScope.reservedSetException)?.(error);") - switch signature.returnType { - case .void: - printer.write("return;") - default: - printer.write("throw error;") - } - } - printer.write("}") + 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("};") + printer.write("}") + + let returnFragment = try! IntrinsicJSFragment.closureLiftReturn(type: signature.returnType) + _ = returnFragment.printCode([invokeResultName], scope, printer, cleanupCode) } printer.write("};") @@ -3552,7 +3578,7 @@ extension BridgeType { return name case .swiftProtocol(let name): return name - case .closure(let signature): + case .closure(let signature, _): let paramTypes = signature.parameters.enumerated().map { index, param in "arg\(index): \(param.tsType)" }.joined(separator: ", ") diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 8d909623..dec77b3c 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -29,6 +29,8 @@ final class JSGlueVariableScope { static let reservedTmpStructCleanups = "tmpStructCleanups" static let reservedEnumHelpers = "enumHelpers" static let reservedStructHelpers = "structHelpers" + static let reservedSwiftClosureRegistry = "swiftClosureRegistry" + static let reservedMakeSwiftClosure = "makeClosure" private let intrinsicRegistry: JSIntrinsicRegistry @@ -56,6 +58,8 @@ final class JSGlueVariableScope { reservedTmpStructCleanups, reservedEnumHelpers, reservedStructHelpers, + reservedSwiftClosureRegistry, + reservedMakeSwiftClosure, ] init(intrinsicRegistry: JSIntrinsicRegistry) { @@ -660,6 +664,9 @@ struct IntrinsicJSFragment: Sendable { } printer.write("}") resultExpr = "\(isSome) ? \(objectLabel) : \(absenceLiteral)" + case .closure: + resultExpr = + "\(isSome) ? \(JSGlueVariableScope.reservedSwift).memory.getObject(\(wrappedValue)) : \(absenceLiteral)" case .swiftHeapObject(let name): resultExpr = "\(isSome) ? \(name).__construct(\(wrappedValue)) : \(absenceLiteral)" case .jsObject: @@ -1392,7 +1399,7 @@ struct IntrinsicJSFragment: Sendable { let absenceLiteral = kind.absenceLiteral switch wrappedType { case .string, .rawValueEnum, .int, .bool, .double, .float, .jsObject, .swiftHeapObject, .caseEnum, - .associatedValueEnum: + .associatedValueEnum, .closure: break default: throw BridgeJSLinkError( @@ -1445,6 +1452,9 @@ struct IntrinsicJSFragment: Sendable { 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)") } @@ -1731,6 +1741,20 @@ struct IntrinsicJSFragment: Sendable { return [] } ) + case .closure: + return IntrinsicJSFragment( + parameters: ["invokeCall"], + printCode: { arguments, scope, printer, cleanupCode in + 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: @@ -1929,14 +1953,12 @@ struct IntrinsicJSFragment: Sendable { case .swiftStruct(let fullName): let base = fullName.components(separatedBy: ".").last ?? fullName return swiftStructLiftReturn(structBase: base) - case .closure(let signature): - let lowerFuncName = "lower_closure_\(signature.moduleName)_\(signature.mangleName)" + case .closure: return IntrinsicJSFragment( - parameters: ["boxPtr"], + parameters: ["funcRef"], printCode: { arguments, scope, printer, cleanupCode in - let boxPtr = arguments[0] - printer.write("return bjs[\"\(lowerFuncName)\"](\(boxPtr));") - return [] + let funcRef = arguments[0] + return ["\(JSGlueVariableScope.reservedSwift).memory.getObject(\(funcRef))"] } ) case .namespaceEnum(let string): @@ -2023,12 +2045,12 @@ struct IntrinsicJSFragment: Sendable { } ) } - case .closure(let signature): - let lowerFuncName = "lower_closure_\(signature.moduleName)_\(signature.mangleName)" + case .closure: return IntrinsicJSFragment( - parameters: ["boxPtr"], + parameters: ["funcRef"], printCode: { arguments, scope, printer, cleanupCode in - return ["bjs[\"\(lowerFuncName)\"](\(arguments[0]))"] + let funcRef = arguments[0] + return ["\(JSGlueVariableScope.reservedSwift).memory.getObject(\(funcRef))"] } ) case .namespaceEnum(let string): diff --git a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift index 3029fe0c..3ebc9130 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift @@ -160,7 +160,7 @@ public enum BridgeType: Codable, Equatable, Hashable, Sendable { case namespaceEnum(String) case swiftProtocol(String) case swiftStruct(String) - indirect case closure(ClosureSignature) + indirect case closure(ClosureSignature, useJSTypedClosure: Bool) } public enum WasmCoreType: String, Codable, Sendable { @@ -1019,12 +1019,12 @@ extension BridgeType { return "\(name.count)\(name)P" case .swiftStruct(let name): return "\(name.count)\(name)V" - case .closure(let signature): + case .closure(let signature, let useJSTypedClosure): let params = signature.parameters.isEmpty ? "y" : signature.parameters.map { $0.mangleTypeName }.joined() - return "K\(params)_\(signature.returnType.mangleTypeName)" + return "K\(params)_\(signature.returnType.mangleTypeName)\(useJSTypedClosure ? "J" : "")" case .array(let elementType): // Array mangling: "Sa" prefix followed by element type return "Sa\(elementType.mangleTypeName)" @@ -1060,3 +1060,16 @@ extension BridgeType { } } } + +extension WasmCoreType { + /// Returns a Swift statement that returns a placeholder value for this Wasm core type. + public var swiftReturnPlaceholderStmt: String { + switch self { + case .i32: return "return 0" + case .i64: return "return 0" + case .f32: return "return 0.0" + case .f64: return "return 0.0" + case .pointer: return "return UnsafeMutableRawPointer(bitPattern: -1).unsafelyUnwrapped" + } + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.json index d7172682..ee551fa4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.json @@ -62,7 +62,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -99,7 +100,8 @@ } } - } + }, + "useJSTypedClosure" : false } } }, @@ -143,7 +145,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -237,7 +240,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -279,7 +283,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -303,7 +308,8 @@ } } - } + }, + "useJSTypedClosure" : false } } }, @@ -343,7 +349,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -372,7 +379,8 @@ } } - } + }, + "useJSTypedClosure" : false } } }, @@ -407,7 +415,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -450,7 +459,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -493,7 +503,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -535,7 +546,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -576,7 +588,8 @@ } } - } + }, + "useJSTypedClosure" : false } } }, @@ -611,7 +624,8 @@ } } - } + }, + "useJSTypedClosure" : false } } }, @@ -646,7 +660,8 @@ } } - } + }, + "useJSTypedClosure" : false } } }, @@ -680,7 +695,8 @@ } } - } + }, + "useJSTypedClosure" : false } } }, @@ -720,7 +736,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -768,7 +785,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -815,7 +833,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -861,7 +880,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift index 94351dbd..e659988d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift @@ -7,18 +7,16 @@ fileprivate func invoke_js_callback_TestModule_10TestModule10HttpStatusO_Si(_ ca } #endif -private final class _BJS_ClosureBox_10TestModule10HttpStatusO_Si: _BridgedSwiftClosureBox { - let closure: (HttpStatus) -> Int - init(_ closure: @escaping (HttpStatus) -> Int) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule10HttpStatusO_Si") +fileprivate func make_swift_closure_TestModule_10TestModule10HttpStatusO_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModule10HttpStatusO_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_10TestModule10HttpStatusO_Si { - static func bridgeJSLower(_ closure: @escaping (HttpStatus) -> Int) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_10TestModule10HttpStatusO_Si(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (HttpStatus) -> Int { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -34,12 +32,23 @@ private enum _BJS_Closure_10TestModule10HttpStatusO_Si { } } +extension JSTypedClosure where Signature == (HttpStatus) -> Int { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (HttpStatus) -> Int) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModule10HttpStatusO_Si, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_TestModule_10TestModule10HttpStatusO_Si") @_cdecl("invoke_swift_closure_TestModule_10TestModule10HttpStatusO_Si") public func _invoke_swift_closure_TestModule_10TestModule10HttpStatusO_Si(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_10TestModule10HttpStatusO_Si>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(HttpStatus.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(HttpStatus) -> Int>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(HttpStatus.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -55,18 +64,16 @@ fileprivate func invoke_js_callback_TestModule_10TestModule5ThemeO_SS(_ callback } #endif -private final class _BJS_ClosureBox_10TestModule5ThemeO_SS: _BridgedSwiftClosureBox { - let closure: (Theme) -> String - init(_ closure: @escaping (Theme) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule5ThemeO_SS") +fileprivate func make_swift_closure_TestModule_10TestModule5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModule5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_10TestModule5ThemeO_SS { - static func bridgeJSLower(_ closure: @escaping (Theme) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_10TestModule5ThemeO_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Theme) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -82,12 +89,23 @@ private enum _BJS_Closure_10TestModule5ThemeO_SS { } } +extension JSTypedClosure where Signature == (Theme) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Theme) -> String) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModule5ThemeO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_TestModule_10TestModule5ThemeO_SS") @_cdecl("invoke_swift_closure_TestModule_10TestModule5ThemeO_SS") public func _invoke_swift_closure_TestModule_10TestModule5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_10TestModule5ThemeO_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Theme.bridgeJSLiftParameter(param0Bytes, param0Length)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Theme) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Theme.bridgeJSLiftParameter(param0Bytes, param0Length)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -103,18 +121,16 @@ fileprivate func invoke_js_callback_TestModule_10TestModule5ThemeO_Sb(_ callback } #endif -private final class _BJS_ClosureBox_10TestModule5ThemeO_Sb: _BridgedSwiftClosureBox { - let closure: (Theme) -> Bool - init(_ closure: @escaping (Theme) -> Bool) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule5ThemeO_Sb") +fileprivate func make_swift_closure_TestModule_10TestModule5ThemeO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModule5ThemeO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_10TestModule5ThemeO_Sb { - static func bridgeJSLower(_ closure: @escaping (Theme) -> Bool) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_10TestModule5ThemeO_Sb(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Theme) -> Bool { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -130,12 +146,23 @@ private enum _BJS_Closure_10TestModule5ThemeO_Sb { } } +extension JSTypedClosure where Signature == (Theme) -> Bool { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Theme) -> Bool) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModule5ThemeO_Sb, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_TestModule_10TestModule5ThemeO_Sb") @_cdecl("invoke_swift_closure_TestModule_10TestModule5ThemeO_Sb") public func _invoke_swift_closure_TestModule_10TestModule5ThemeO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_10TestModule5ThemeO_Sb>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Theme.bridgeJSLiftParameter(param0Bytes, param0Length)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Theme) -> Bool>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Theme.bridgeJSLiftParameter(param0Bytes, param0Length)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -151,18 +178,16 @@ fileprivate func invoke_js_callback_TestModule_10TestModule6PersonC_SS(_ callbac } #endif -private final class _BJS_ClosureBox_10TestModule6PersonC_SS: _BridgedSwiftClosureBox { - let closure: (Person) -> String - init(_ closure: @escaping (Person) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule6PersonC_SS") +fileprivate func make_swift_closure_TestModule_10TestModule6PersonC_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModule6PersonC_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_10TestModule6PersonC_SS { - static func bridgeJSLower(_ closure: @escaping (Person) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_10TestModule6PersonC_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Person) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -178,12 +203,23 @@ private enum _BJS_Closure_10TestModule6PersonC_SS { } } +extension JSTypedClosure where Signature == (Person) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Person) -> String) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModule6PersonC_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_TestModule_10TestModule6PersonC_SS") @_cdecl("invoke_swift_closure_TestModule_10TestModule6PersonC_SS") public func _invoke_swift_closure_TestModule_10TestModule6PersonC_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_10TestModule6PersonC_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Person.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Person) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Person.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -199,18 +235,16 @@ fileprivate func invoke_js_callback_TestModule_10TestModule9APIResultO_SS(_ call } #endif -private final class _BJS_ClosureBox_10TestModule9APIResultO_SS: _BridgedSwiftClosureBox { - let closure: (APIResult) -> String - init(_ closure: @escaping (APIResult) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule9APIResultO_SS") +fileprivate func make_swift_closure_TestModule_10TestModule9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModule9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_10TestModule9APIResultO_SS { - static func bridgeJSLower(_ closure: @escaping (APIResult) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_10TestModule9APIResultO_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (APIResult) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -226,12 +260,23 @@ private enum _BJS_Closure_10TestModule9APIResultO_SS { } } +extension JSTypedClosure where Signature == (APIResult) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (APIResult) -> String) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModule9APIResultO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_TestModule_10TestModule9APIResultO_SS") @_cdecl("invoke_swift_closure_TestModule_10TestModule9APIResultO_SS") public func _invoke_swift_closure_TestModule_10TestModule9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_10TestModule9APIResultO_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(APIResult.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(APIResult) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(APIResult.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -247,18 +292,16 @@ fileprivate func invoke_js_callback_TestModule_10TestModule9DirectionO_SS(_ call } #endif -private final class _BJS_ClosureBox_10TestModule9DirectionO_SS: _BridgedSwiftClosureBox { - let closure: (Direction) -> String - init(_ closure: @escaping (Direction) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule9DirectionO_SS") +fileprivate func make_swift_closure_TestModule_10TestModule9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModule9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_10TestModule9DirectionO_SS { - static func bridgeJSLower(_ closure: @escaping (Direction) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_10TestModule9DirectionO_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Direction) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -274,12 +317,23 @@ private enum _BJS_Closure_10TestModule9DirectionO_SS { } } +extension JSTypedClosure where Signature == (Direction) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Direction) -> String) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModule9DirectionO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_TestModule_10TestModule9DirectionO_SS") @_cdecl("invoke_swift_closure_TestModule_10TestModule9DirectionO_SS") public func _invoke_swift_closure_TestModule_10TestModule9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_10TestModule9DirectionO_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Direction.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Direction) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Direction.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -295,18 +349,16 @@ fileprivate func invoke_js_callback_TestModule_10TestModule9DirectionO_Sb(_ call } #endif -private final class _BJS_ClosureBox_10TestModule9DirectionO_Sb: _BridgedSwiftClosureBox { - let closure: (Direction) -> Bool - init(_ closure: @escaping (Direction) -> Bool) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule9DirectionO_Sb") +fileprivate func make_swift_closure_TestModule_10TestModule9DirectionO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModule9DirectionO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_10TestModule9DirectionO_Sb { - static func bridgeJSLower(_ closure: @escaping (Direction) -> Bool) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_10TestModule9DirectionO_Sb(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Direction) -> Bool { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -322,12 +374,23 @@ private enum _BJS_Closure_10TestModule9DirectionO_Sb { } } +extension JSTypedClosure where Signature == (Direction) -> Bool { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Direction) -> Bool) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModule9DirectionO_Sb, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_TestModule_10TestModule9DirectionO_Sb") @_cdecl("invoke_swift_closure_TestModule_10TestModule9DirectionO_Sb") public func _invoke_swift_closure_TestModule_10TestModule9DirectionO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_10TestModule9DirectionO_Sb>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Direction.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Direction) -> Bool>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Direction.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -343,18 +406,16 @@ fileprivate func invoke_js_callback_TestModule_10TestModuleSS_SS(_ callback: Int } #endif -private final class _BJS_ClosureBox_10TestModuleSS_SS: _BridgedSwiftClosureBox { - let closure: (String) -> String - init(_ closure: @escaping (String) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSS_SS") +fileprivate func make_swift_closure_TestModule_10TestModuleSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_10TestModuleSS_SS { - static func bridgeJSLower(_ closure: @escaping (String) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_10TestModuleSS_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (String) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -370,12 +431,23 @@ private enum _BJS_Closure_10TestModuleSS_SS { } } +extension JSTypedClosure where Signature == (String) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (String) -> String) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSS_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSS_SS") @_cdecl("invoke_swift_closure_TestModule_10TestModuleSS_SS") public func _invoke_swift_closure_TestModule_10TestModuleSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_10TestModuleSS_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(String.bridgeJSLiftParameter(param0Bytes, param0Length)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(String) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(String.bridgeJSLiftParameter(param0Bytes, param0Length)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -391,18 +463,16 @@ fileprivate func invoke_js_callback_TestModule_10TestModuleSq5ThemeO_SS(_ callba } #endif -private final class _BJS_ClosureBox_10TestModuleSq5ThemeO_SS: _BridgedSwiftClosureBox { - let closure: (Optional) -> String - init(_ closure: @escaping (Optional) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq5ThemeO_SS") +fileprivate func make_swift_closure_TestModule_10TestModuleSq5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSq5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_10TestModuleSq5ThemeO_SS { - static func bridgeJSLower(_ closure: @escaping (Optional) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_10TestModuleSq5ThemeO_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -418,12 +488,23 @@ private enum _BJS_Closure_10TestModuleSq5ThemeO_SS { } } +extension JSTypedClosure where Signature == (Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSq5ThemeO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_SS") @_cdecl("invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_SS") public func _invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_10TestModuleSq5ThemeO_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Bytes, param0Length)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Bytes, param0Length)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -439,18 +520,16 @@ fileprivate func invoke_js_callback_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS } #endif -private final class _BJS_ClosureBox_10TestModuleSq6PersonCSqSSSqSd_SS: _BridgedSwiftClosureBox { - let closure: (Optional, Optional, Optional) -> String - init(_ closure: @escaping (Optional, Optional, Optional) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS") +fileprivate func make_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_10TestModuleSq6PersonCSqSSSqSd_SS { - static func bridgeJSLower(_ closure: @escaping (Optional, Optional, Optional) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_10TestModuleSq6PersonCSqSSSqSd_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Optional, Optional, Optional) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0, param1, param2 in @@ -468,12 +547,23 @@ private enum _BJS_Closure_10TestModuleSq6PersonCSqSSSqSd_SS { } } +extension JSTypedClosure where Signature == (Optional, Optional, Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional, Optional, Optional) -> String) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS") @_cdecl("invoke_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS") public func _invoke_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: UnsafeMutableRawPointer, _ param1IsSome: Int32, _ param1Bytes: Int32, _ param1Length: Int32, _ param2IsSome: Int32, _ param2Value: Float64) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_10TestModuleSq6PersonCSqSSSqSd_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value), Optional.bridgeJSLiftParameter(param1IsSome, param1Bytes, param1Length), Optional.bridgeJSLiftParameter(param2IsSome, param2Value)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional, Optional, Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value), Optional.bridgeJSLiftParameter(param1IsSome, param1Bytes, param1Length), Optional.bridgeJSLiftParameter(param2IsSome, param2Value)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -489,18 +579,16 @@ fileprivate func invoke_js_callback_TestModule_10TestModuleSq6PersonC_SS(_ callb } #endif -private final class _BJS_ClosureBox_10TestModuleSq6PersonC_SS: _BridgedSwiftClosureBox { - let closure: (Optional) -> String - init(_ closure: @escaping (Optional) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq6PersonC_SS") +fileprivate func make_swift_closure_TestModule_10TestModuleSq6PersonC_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSq6PersonC_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_10TestModuleSq6PersonC_SS { - static func bridgeJSLower(_ closure: @escaping (Optional) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_10TestModuleSq6PersonC_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -516,12 +604,23 @@ private enum _BJS_Closure_10TestModuleSq6PersonC_SS { } } +extension JSTypedClosure where Signature == (Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSq6PersonC_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq6PersonC_SS") @_cdecl("invoke_swift_closure_TestModule_10TestModuleSq6PersonC_SS") public func _invoke_swift_closure_TestModule_10TestModuleSq6PersonC_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_10TestModuleSq6PersonC_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -537,18 +636,16 @@ fileprivate func invoke_js_callback_TestModule_10TestModuleSq9APIResultO_SS(_ ca } #endif -private final class _BJS_ClosureBox_10TestModuleSq9APIResultO_SS: _BridgedSwiftClosureBox { - let closure: (Optional) -> String - init(_ closure: @escaping (Optional) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq9APIResultO_SS") +fileprivate func make_swift_closure_TestModule_10TestModuleSq9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSq9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_10TestModuleSq9APIResultO_SS { - static func bridgeJSLower(_ closure: @escaping (Optional) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_10TestModuleSq9APIResultO_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -564,12 +661,23 @@ private enum _BJS_Closure_10TestModuleSq9APIResultO_SS { } } +extension JSTypedClosure where Signature == (Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSq9APIResultO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_SS") @_cdecl("invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_SS") public func _invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_10TestModuleSq9APIResultO_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Optional.bridgeJSLiftParameter(param0IsSome, param0CaseId)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0CaseId)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -585,18 +693,16 @@ fileprivate func invoke_js_callback_TestModule_10TestModuleSq9DirectionO_SS(_ ca } #endif -private final class _BJS_ClosureBox_10TestModuleSq9DirectionO_SS: _BridgedSwiftClosureBox { - let closure: (Optional) -> String - init(_ closure: @escaping (Optional) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq9DirectionO_SS") +fileprivate func make_swift_closure_TestModule_10TestModuleSq9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSq9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_10TestModuleSq9DirectionO_SS { - static func bridgeJSLower(_ closure: @escaping (Optional) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_10TestModuleSq9DirectionO_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -612,12 +718,23 @@ private enum _BJS_Closure_10TestModuleSq9DirectionO_SS { } } +extension JSTypedClosure where Signature == (Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSq9DirectionO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_SS") @_cdecl("invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_SS") public func _invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_10TestModuleSq9DirectionO_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -799,10 +916,10 @@ public func _bjs_TestProcessor_init(_ transform: Int32) -> UnsafeMutableRawPoint @_expose(wasm, "bjs_TestProcessor_getTransform") @_cdecl("bjs_TestProcessor_getTransform") -public func _bjs_TestProcessor_getTransform(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +public func _bjs_TestProcessor_getTransform(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) let ret = TestProcessor.bridgeJSLiftParameter(_self).getTransform() - return _BJS_Closure_10TestModuleSS_SS.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -832,10 +949,10 @@ public func _bjs_TestProcessor_printTogether(_ _self: UnsafeMutableRawPointer, _ @_expose(wasm, "bjs_TestProcessor_roundtrip") @_cdecl("bjs_TestProcessor_roundtrip") -public func _bjs_TestProcessor_roundtrip(_ _self: UnsafeMutableRawPointer, _ personClosure: Int32) -> UnsafeMutableRawPointer { +public func _bjs_TestProcessor_roundtrip(_ _self: UnsafeMutableRawPointer, _ personClosure: Int32) -> Int32 { #if arch(wasm32) let ret = TestProcessor.bridgeJSLiftParameter(_self).roundtrip(_: _BJS_Closure_10TestModule6PersonC_SS.bridgeJSLift(personClosure)) - return _BJS_Closure_10TestModule6PersonC_SS.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -843,10 +960,10 @@ public func _bjs_TestProcessor_roundtrip(_ _self: UnsafeMutableRawPointer, _ per @_expose(wasm, "bjs_TestProcessor_roundtripOptional") @_cdecl("bjs_TestProcessor_roundtripOptional") -public func _bjs_TestProcessor_roundtripOptional(_ _self: UnsafeMutableRawPointer, _ personClosure: Int32) -> UnsafeMutableRawPointer { +public func _bjs_TestProcessor_roundtripOptional(_ _self: UnsafeMutableRawPointer, _ personClosure: Int32) -> Int32 { #if arch(wasm32) let ret = TestProcessor.bridgeJSLiftParameter(_self).roundtripOptional(_: _BJS_Closure_10TestModuleSq6PersonC_SS.bridgeJSLift(personClosure)) - return _BJS_Closure_10TestModuleSq6PersonC_SS.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -898,10 +1015,10 @@ public func _bjs_TestProcessor_processAPIResult(_ _self: UnsafeMutableRawPointer @_expose(wasm, "bjs_TestProcessor_makeDirectionChecker") @_cdecl("bjs_TestProcessor_makeDirectionChecker") -public func _bjs_TestProcessor_makeDirectionChecker(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +public func _bjs_TestProcessor_makeDirectionChecker(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) let ret = TestProcessor.bridgeJSLiftParameter(_self).makeDirectionChecker() - return _BJS_Closure_10TestModule9DirectionO_Sb.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -909,10 +1026,10 @@ public func _bjs_TestProcessor_makeDirectionChecker(_ _self: UnsafeMutableRawPoi @_expose(wasm, "bjs_TestProcessor_makeThemeValidator") @_cdecl("bjs_TestProcessor_makeThemeValidator") -public func _bjs_TestProcessor_makeThemeValidator(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +public func _bjs_TestProcessor_makeThemeValidator(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) let ret = TestProcessor.bridgeJSLiftParameter(_self).makeThemeValidator() - return _BJS_Closure_10TestModule5ThemeO_Sb.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -920,10 +1037,10 @@ public func _bjs_TestProcessor_makeThemeValidator(_ _self: UnsafeMutableRawPoint @_expose(wasm, "bjs_TestProcessor_makeStatusCodeExtractor") @_cdecl("bjs_TestProcessor_makeStatusCodeExtractor") -public func _bjs_TestProcessor_makeStatusCodeExtractor(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +public func _bjs_TestProcessor_makeStatusCodeExtractor(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) let ret = TestProcessor.bridgeJSLiftParameter(_self).makeStatusCodeExtractor() - return _BJS_Closure_10TestModule10HttpStatusO_Si.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -931,10 +1048,10 @@ public func _bjs_TestProcessor_makeStatusCodeExtractor(_ _self: UnsafeMutableRaw @_expose(wasm, "bjs_TestProcessor_makeAPIResultHandler") @_cdecl("bjs_TestProcessor_makeAPIResultHandler") -public func _bjs_TestProcessor_makeAPIResultHandler(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +public func _bjs_TestProcessor_makeAPIResultHandler(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) let ret = TestProcessor.bridgeJSLiftParameter(_self).makeAPIResultHandler() - return _BJS_Closure_10TestModule9APIResultO_SS.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -975,10 +1092,10 @@ public func _bjs_TestProcessor_processOptionalAPIResult(_ _self: UnsafeMutableRa @_expose(wasm, "bjs_TestProcessor_makeOptionalDirectionFormatter") @_cdecl("bjs_TestProcessor_makeOptionalDirectionFormatter") -public func _bjs_TestProcessor_makeOptionalDirectionFormatter(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +public func _bjs_TestProcessor_makeOptionalDirectionFormatter(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) let ret = TestProcessor.bridgeJSLiftParameter(_self).makeOptionalDirectionFormatter() - return _BJS_Closure_10TestModuleSq9DirectionO_SS.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.json index 9e0e0a49..0013c810 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.json @@ -35,7 +35,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -77,7 +78,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.swift index c833a54d..c42c3b36 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.swift @@ -7,18 +7,16 @@ fileprivate func invoke_js_callback_TestModule_10TestModuleSi_Si(_ callback: Int } #endif -private final class _BJS_ClosureBox_10TestModuleSi_Si: _BridgedSwiftClosureBox { - let closure: (Int) -> Int - init(_ closure: @escaping (Int) -> Int) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSi_Si") +fileprivate func make_swift_closure_TestModule_10TestModuleSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_10TestModuleSi_Si { - static func bridgeJSLower(_ closure: @escaping (Int) -> Int) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_10TestModuleSi_Si(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Int) -> Int { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -34,12 +32,23 @@ private enum _BJS_Closure_10TestModuleSi_Si { } } +extension JSTypedClosure where Signature == (Int) -> Int { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Int) -> Int) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSi_Si, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSi_Si") @_cdecl("invoke_swift_closure_TestModule_10TestModuleSi_Si") public func _invoke_swift_closure_TestModule_10TestModuleSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_10TestModuleSi_Si>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Int.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Int) -> Int>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Int.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -48,17 +57,20 @@ public func _invoke_swift_closure_TestModule_10TestModuleSi_Si(_ boxPtr: UnsafeM #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_applyInt") -fileprivate func bjs_applyInt(_ value: Int32, _ transform: UnsafeMutableRawPointer) -> Int32 +fileprivate func bjs_applyInt(_ value: Int32, _ transform: Int32) -> Int32 #else -fileprivate func bjs_applyInt(_ value: Int32, _ transform: UnsafeMutableRawPointer) -> Int32 { +fileprivate func bjs_applyInt(_ value: Int32, _ transform: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif func _$applyInt(_ value: Int, _ transform: @escaping (Int) -> Int) throws(JSException) -> Int { let valueValue = value.bridgeJSLowerParameter() - let transformPointer = _BJS_Closure_10TestModuleSi_Si.bridgeJSLower(transform) - let ret = bjs_applyInt(valueValue, transformPointer) + let transform = JSTypedClosure<(Int) -> Int>(transform) + let transformFuncRef = transform.bridgeJSLowerParameter() + let ret = withExtendedLifetime((transform)) { + bjs_applyInt(valueValue, transformFuncRef) + } if let error = _swift_js_take_exception() { throw error } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js index bc0def6f..a6966ae4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js @@ -60,6 +60,31 @@ export async function createInstantiator(options, swift) { let _exports = null; let bjs = null; + const swiftClosureRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.unregistered) { return; } + instance?.exports?.bjs_release_swift_closure(state.pointer); + }); + const makeClosure = (pointer, file, line, func) => { + const state = { pointer, file, line, unregistered: false }; + const real = (...args) => { + if (state.unregistered) { + const bytes = new Uint8Array(memory.buffer, state.file); + let length = 0; + while (bytes[length] !== 0) { length += 1; } + const fileID = textDecoder.decode(bytes.subarray(0, length)); + throw new Error(`Attempted to call a released JSTypedClosure created at ${fileID}:${state.line}`); + } + return func(...args); + }; + real.__unregister = () => { + if (state.unregistered) { return; } + state.unregistered = true; + swiftClosureRegistry.unregister(state); + }; + swiftClosureRegistry.register(real, state, state); + return swift.memory.retain(real); + }; + const __bjs_createAPIResultValuesHelpers = () => { return () => ({ lower: (value) => { @@ -298,6 +323,10 @@ export async function createInstantiator(options, swift) { tmpRetOptionalHeapObject = undefined; return pointer || 0; } + bjs["swift_js_closure_unregister"] = function(funcRef) { + const func = swift.memory.getObject(funcRef); + func.__unregister(); + } bjs["invoke_js_callback_TestModule_10TestModule10HttpStatusO_Si"] = function(callbackId, param0Id) { try { @@ -310,17 +339,19 @@ export async function createInstantiator(options, swift) { return 0; } }; - - bjs["lower_closure_TestModule_10TestModule10HttpStatusO_Si"] = function(closurePtr) { - return function(param0) { - try { - return instance.exports.invoke_swift_closure_TestModule_10TestModule10HttpStatusO_Si(closurePtr, param0) | 0; - } catch (error) { - setException?.(error); + bjs["make_swift_closure_TestModule_10TestModule10HttpStatusO_Si"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule10HttpStatusO_Si = function(param0) { + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule10HttpStatusO_Si(boxPtr, param0); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; throw error; } + return invokeResult | 0; }; - }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule10HttpStatusO_Si); + } bjs["invoke_js_callback_TestModule_10TestModule5ThemeO_SS"] = function(callbackId, param0Id) { try { @@ -340,22 +371,24 @@ export async function createInstantiator(options, swift) { return 0; } }; - - bjs["lower_closure_TestModule_10TestModule5ThemeO_SS"] = function(closurePtr) { - return function(param0) { - try { - const param0Bytes = textEncoder.encode(param0); - const param0Id = swift.memory.retain(param0Bytes); - const resultLen = instance.exports.invoke_swift_closure_TestModule_10TestModule5ThemeO_SS(closurePtr, param0Id, param0Bytes.length); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } catch (error) { - setException?.(error); + bjs["make_swift_closure_TestModule_10TestModule5ThemeO_SS"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule5ThemeO_SS = function(param0) { + const param0Bytes = textEncoder.encode(param0); + const param0Id = swift.memory.retain(param0Bytes); + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule5ThemeO_SS(boxPtr, param0Id, param0Bytes.length); + 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_SS); + } bjs["invoke_js_callback_TestModule_10TestModule5ThemeO_Sb"] = function(callbackId, param0Id) { try { @@ -370,19 +403,21 @@ export async function createInstantiator(options, swift) { return 0; } }; - - bjs["lower_closure_TestModule_10TestModule5ThemeO_Sb"] = function(closurePtr) { - return function(param0) { - try { - const param0Bytes = textEncoder.encode(param0); - const param0Id = swift.memory.retain(param0Bytes); - return instance.exports.invoke_swift_closure_TestModule_10TestModule5ThemeO_Sb(closurePtr, param0Id, param0Bytes.length) !== 0; - } catch (error) { - setException?.(error); + bjs["make_swift_closure_TestModule_10TestModule5ThemeO_Sb"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule5ThemeO_Sb = function(param0) { + const param0Bytes = textEncoder.encode(param0); + const param0Id = swift.memory.retain(param0Bytes); + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule5ThemeO_Sb(boxPtr, param0Id, param0Bytes.length); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; throw error; } + return invokeResult !== 0; }; - }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule5ThemeO_Sb); + } bjs["invoke_js_callback_TestModule_10TestModule6PersonC_SS"] = function(callbackId, param0Id) { try { @@ -400,20 +435,22 @@ export async function createInstantiator(options, swift) { return 0; } }; - - bjs["lower_closure_TestModule_10TestModule6PersonC_SS"] = function(closurePtr) { - return function(param0) { - try { - const resultLen = instance.exports.invoke_swift_closure_TestModule_10TestModule6PersonC_SS(closurePtr, param0.pointer); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } catch (error) { - setException?.(error); + bjs["make_swift_closure_TestModule_10TestModule6PersonC_SS"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule6PersonC_SS = function(param0) { + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule6PersonC_SS(boxPtr, param0.pointer); + 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_10TestModule6PersonC_SS); + } bjs["invoke_js_callback_TestModule_10TestModule9APIResultO_SS"] = function(callbackId, param0Id) { try { @@ -431,21 +468,23 @@ export async function createInstantiator(options, swift) { return 0; } }; - - bjs["lower_closure_TestModule_10TestModule9APIResultO_SS"] = function(closurePtr) { - return function(param0) { - try { - const { caseId: param0CaseId, cleanup: param0Cleanup } = enumHelpers.APIResult.lower(param0); - const resultLen = instance.exports.invoke_swift_closure_TestModule_10TestModule9APIResultO_SS(closurePtr, param0CaseId); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } catch (error) { - setException?.(error); + bjs["make_swift_closure_TestModule_10TestModule9APIResultO_SS"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule9APIResultO_SS = function(param0) { + const { caseId: param0CaseId, cleanup: param0Cleanup } = enumHelpers.APIResult.lower(param0); + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule9APIResultO_SS(boxPtr, param0CaseId); + 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_10TestModule9APIResultO_SS); + } bjs["invoke_js_callback_TestModule_10TestModule9DirectionO_SS"] = function(callbackId, param0Id) { try { @@ -463,20 +502,22 @@ export async function createInstantiator(options, swift) { return 0; } }; - - bjs["lower_closure_TestModule_10TestModule9DirectionO_SS"] = function(closurePtr) { - return function(param0) { - try { - const resultLen = instance.exports.invoke_swift_closure_TestModule_10TestModule9DirectionO_SS(closurePtr, param0); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } catch (error) { - setException?.(error); + bjs["make_swift_closure_TestModule_10TestModule9DirectionO_SS"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule9DirectionO_SS = function(param0) { + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule9DirectionO_SS(boxPtr, param0); + 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_10TestModule9DirectionO_SS); + } bjs["invoke_js_callback_TestModule_10TestModule9DirectionO_Sb"] = function(callbackId, param0Id) { try { @@ -489,17 +530,19 @@ export async function createInstantiator(options, swift) { return 0; } }; - - bjs["lower_closure_TestModule_10TestModule9DirectionO_Sb"] = function(closurePtr) { - return function(param0) { - try { - return instance.exports.invoke_swift_closure_TestModule_10TestModule9DirectionO_Sb(closurePtr, param0) !== 0; - } catch (error) { - setException?.(error); + bjs["make_swift_closure_TestModule_10TestModule9DirectionO_Sb"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule9DirectionO_Sb = function(param0) { + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule9DirectionO_Sb(boxPtr, param0); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; throw error; } + return invokeResult !== 0; }; - }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule9DirectionO_Sb); + } bjs["invoke_js_callback_TestModule_10TestModuleSS_SS"] = function(callbackId, param0Id) { try { @@ -519,22 +562,24 @@ export async function createInstantiator(options, swift) { return 0; } }; - - bjs["lower_closure_TestModule_10TestModuleSS_SS"] = function(closurePtr) { - return function(param0) { - try { - const param0Bytes = textEncoder.encode(param0); - const param0Id = swift.memory.retain(param0Bytes); - const resultLen = instance.exports.invoke_swift_closure_TestModule_10TestModuleSS_SS(closurePtr, param0Id, param0Bytes.length); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } catch (error) { - 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); + 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_10TestModuleSq5ThemeO_SS"] = function(callbackId, param0IsSome, param0Value) { try { @@ -559,26 +604,28 @@ export async function createInstantiator(options, swift) { return 0; } }; - - bjs["lower_closure_TestModule_10TestModuleSq5ThemeO_SS"] = function(closurePtr) { - return function(param0) { - try { - const isSome = param0 != null; - let param0Id, param0Bytes; - if (isSome) { - param0Bytes = textEncoder.encode(param0); - param0Id = swift.memory.retain(param0Bytes); - } - const resultLen = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_SS(closurePtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } catch (error) { - setException?.(error); + bjs["make_swift_closure_TestModule_10TestModuleSq5ThemeO_SS"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSq5ThemeO_SS = function(param0) { + const isSome = param0 != null; + let param0Id, param0Bytes; + if (isSome) { + param0Bytes = textEncoder.encode(param0); + param0Id = swift.memory.retain(param0Bytes); + } + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_SS(boxPtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); + 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_10TestModuleSq5ThemeO_SS); + } bjs["invoke_js_callback_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS"] = function(callbackId, param0IsSome, param0Value, param1IsSome, param1Value, param2IsSome, param2Value) { try { @@ -615,28 +662,30 @@ export async function createInstantiator(options, swift) { return 0; } }; - - bjs["lower_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS"] = function(closurePtr) { - return function(param0, param1, param2) { - try { - const isSome = param0 != null; - const isSome1 = param1 != null; - let param1Id, param1Bytes; - if (isSome1) { - param1Bytes = textEncoder.encode(param1); - param1Id = swift.memory.retain(param1Bytes); - } - const isSome2 = param2 != null; - const resultLen = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS(closurePtr, +isSome, isSome ? param0.pointer : 0, +isSome1, isSome1 ? param1Id : 0, isSome1 ? param1Bytes.length : 0, +isSome2, isSome2 ? param2 : 0); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } catch (error) { - setException?.(error); + bjs["make_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS = function(param0, param1, param2) { + const isSome = param0 != null; + const isSome1 = param1 != null; + let param1Id, param1Bytes; + if (isSome1) { + param1Bytes = textEncoder.encode(param1); + param1Id = swift.memory.retain(param1Bytes); + } + const isSome2 = param2 != null; + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS(boxPtr, +isSome, isSome ? param0.pointer : 0, +isSome1, isSome1 ? param1Id : 0, isSome1 ? param1Bytes.length : 0, +isSome2, isSome2 ? param2 : 0); + 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_10TestModuleSq6PersonCSqSSSqSd_SS); + } bjs["invoke_js_callback_TestModule_10TestModuleSq6PersonC_SS"] = function(callbackId, param0IsSome, param0Value) { try { @@ -659,21 +708,23 @@ export async function createInstantiator(options, swift) { return 0; } }; - - bjs["lower_closure_TestModule_10TestModuleSq6PersonC_SS"] = function(closurePtr) { - return function(param0) { - try { - const isSome = param0 != null; - const resultLen = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq6PersonC_SS(closurePtr, +isSome, isSome ? param0.pointer : 0); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } catch (error) { - setException?.(error); + bjs["make_swift_closure_TestModule_10TestModuleSq6PersonC_SS"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSq6PersonC_SS = function(param0) { + const isSome = param0 != null; + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq6PersonC_SS(boxPtr, +isSome, isSome ? param0.pointer : 0); + 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_10TestModuleSq6PersonC_SS); + } bjs["invoke_js_callback_TestModule_10TestModuleSq9APIResultO_SS"] = function(callbackId, param0IsSome, param0Value) { try { @@ -696,27 +747,29 @@ export async function createInstantiator(options, swift) { return 0; } }; - - bjs["lower_closure_TestModule_10TestModuleSq9APIResultO_SS"] = function(closurePtr) { - return function(param0) { - try { - const isSome = param0 != null; - let param0CaseId, param0Cleanup; - if (isSome) { - const enumResult = enumHelpers.APIResult.lower(param0); - param0CaseId = enumResult.caseId; - param0Cleanup = enumResult.cleanup; - } - const resultLen = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_SS(closurePtr, +isSome, isSome ? param0CaseId : 0); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } catch (error) { - setException?.(error); + bjs["make_swift_closure_TestModule_10TestModuleSq9APIResultO_SS"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSq9APIResultO_SS = function(param0) { + const isSome = param0 != null; + let param0CaseId, param0Cleanup; + if (isSome) { + const enumResult = enumHelpers.APIResult.lower(param0); + param0CaseId = enumResult.caseId; + param0Cleanup = enumResult.cleanup; + } + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_SS(boxPtr, +isSome, isSome ? param0CaseId : 0); + 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_10TestModuleSq9APIResultO_SS); + } bjs["invoke_js_callback_TestModule_10TestModuleSq9DirectionO_SS"] = function(callbackId, param0IsSome, param0Value) { try { @@ -739,21 +792,23 @@ export async function createInstantiator(options, swift) { return 0; } }; - - bjs["lower_closure_TestModule_10TestModuleSq9DirectionO_SS"] = function(closurePtr) { - return function(param0) { - try { - const isSome = param0 != null; - const resultLen = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_SS(closurePtr, +isSome, isSome ? param0 : 0); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } catch (error) { - setException?.(error); + bjs["make_swift_closure_TestModule_10TestModuleSq9DirectionO_SS"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSq9DirectionO_SS = function(param0) { + const isSome = param0 != null; + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_SS(boxPtr, +isSome, isSome ? param0 : 0); + 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_10TestModuleSq9DirectionO_SS); + } // Wrapper functions for module: TestModule if (!importObject["TestModule"]) { importObject["TestModule"] = {}; @@ -822,7 +877,7 @@ export async function createInstantiator(options, swift) { } getTransform() { const ret = instance.exports.bjs_TestProcessor_getTransform(this.pointer); - return bjs["lower_closure_TestModule_10TestModuleSS_SS"](ret); + return swift.memory.getObject(ret); } processWithCustom(text, customTransform) { const textBytes = textEncoder.encode(text); @@ -847,12 +902,12 @@ export async function createInstantiator(options, swift) { roundtrip(personClosure) { const callbackId = swift.memory.retain(personClosure); const ret = instance.exports.bjs_TestProcessor_roundtrip(this.pointer, callbackId); - return bjs["lower_closure_TestModule_10TestModule6PersonC_SS"](ret); + return swift.memory.getObject(ret); } roundtripOptional(personClosure) { const callbackId = swift.memory.retain(personClosure); const ret = instance.exports.bjs_TestProcessor_roundtripOptional(this.pointer, callbackId); - return bjs["lower_closure_TestModule_10TestModuleSq6PersonC_SS"](ret); + return swift.memory.getObject(ret); } processDirection(callback) { const callbackId = swift.memory.retain(callback); @@ -882,19 +937,19 @@ export async function createInstantiator(options, swift) { } makeDirectionChecker() { const ret = instance.exports.bjs_TestProcessor_makeDirectionChecker(this.pointer); - return bjs["lower_closure_TestModule_10TestModule9DirectionO_Sb"](ret); + return swift.memory.getObject(ret); } makeThemeValidator() { const ret = instance.exports.bjs_TestProcessor_makeThemeValidator(this.pointer); - return bjs["lower_closure_TestModule_10TestModule5ThemeO_Sb"](ret); + return swift.memory.getObject(ret); } makeStatusCodeExtractor() { const ret = instance.exports.bjs_TestProcessor_makeStatusCodeExtractor(this.pointer); - return bjs["lower_closure_TestModule_10TestModule10HttpStatusO_Si"](ret); + return swift.memory.getObject(ret); } makeAPIResultHandler() { const ret = instance.exports.bjs_TestProcessor_makeAPIResultHandler(this.pointer); - return bjs["lower_closure_TestModule_10TestModule9APIResultO_SS"](ret); + return swift.memory.getObject(ret); } processOptionalDirection(callback) { const callbackId = swift.memory.retain(callback); @@ -919,7 +974,7 @@ export async function createInstantiator(options, swift) { } makeOptionalDirectionFormatter() { const ret = instance.exports.bjs_TestProcessor_makeOptionalDirectionFormatter(this.pointer); - return bjs["lower_closure_TestModule_10TestModuleSq9DirectionO_SS"](ret); + return swift.memory.getObject(ret); } } const APIResultHelpers = __bjs_createAPIResultValuesHelpers()(); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js index 6c1397ff..c61b7131 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js @@ -30,6 +30,31 @@ export async function createInstantiator(options, swift) { let _exports = null; let bjs = null; + const swiftClosureRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.unregistered) { return; } + instance?.exports?.bjs_release_swift_closure(state.pointer); + }); + const makeClosure = (pointer, file, line, func) => { + const state = { pointer, file, line, unregistered: false }; + const real = (...args) => { + if (state.unregistered) { + const bytes = new Uint8Array(memory.buffer, state.file); + let length = 0; + while (bytes[length] !== 0) { length += 1; } + const fileID = textDecoder.decode(bytes.subarray(0, length)); + throw new Error(`Attempted to call a released JSTypedClosure created at ${fileID}:${state.line}`); + } + return func(...args); + }; + real.__unregister = () => { + if (state.unregistered) { return; } + state.unregistered = true; + swiftClosureRegistry.unregister(state); + }; + swiftClosureRegistry.register(real, state, state); + return swift.memory.retain(real); + }; + return { /** @@ -198,6 +223,10 @@ export async function createInstantiator(options, swift) { tmpRetOptionalHeapObject = undefined; return pointer || 0; } + bjs["swift_js_closure_unregister"] = function(funcRef) { + const func = swift.memory.getObject(funcRef); + func.__unregister(); + } bjs["invoke_js_callback_TestModule_10TestModuleSi_Si"] = function(callbackId, param0Id) { try { @@ -210,21 +239,23 @@ export async function createInstantiator(options, swift) { return 0; } }; - - bjs["lower_closure_TestModule_10TestModuleSi_Si"] = function(closurePtr) { - return function(param0) { - try { - return instance.exports.invoke_swift_closure_TestModule_10TestModuleSi_Si(closurePtr, param0) | 0; - } catch (error) { - setException?.(error); + 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); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; throw error; } + return invokeResult | 0; }; - }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSi_Si); + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_applyInt"] = function bjs_applyInt(value, transform) { try { - let ret = imports.applyInt(value, bjs["lower_closure_TestModule_10TestModuleSi_Si"](transform)); + let ret = imports.applyInt(value, swift.memory.getObject(transform)); return ret; } catch (error) { setException(error); diff --git a/Plugins/PackageToJS/Templates/instantiate.js b/Plugins/PackageToJS/Templates/instantiate.js index c17d7884..a0920964 100644 --- a/Plugins/PackageToJS/Templates/instantiate.js +++ b/Plugins/PackageToJS/Templates/instantiate.js @@ -65,6 +65,7 @@ async function createInstantiator(options, swift) { swift_js_push_pointer: unexpectedBjsCall, swift_js_pop_pointer: unexpectedBjsCall, swift_js_struct_cleanup: unexpectedBjsCall, + swift_js_closure_unregister: unexpectedBjsCall, } }, /** @param {WebAssembly.Instance} instance */ diff --git a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift index fd2cbd90..4c8fdf3d 100644 --- a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift +++ b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift @@ -49,6 +49,40 @@ import _CJavaScriptKit #endif } +/// Releases a Swift closure from the FinalizationRegistry +/// +/// This function is called by the BridgeJS code generator when a Swift closure is released. +/// The closure is released from the FinalizationRegistry so it can be garbage collected to +/// balance the +/// +/// - Parameter pointer: The pointer to `_BridgeJSTypedClosureBox` instance +@_expose(wasm, "bjs_release_swift_closure") +public func _bjs_release_swift_closure(_ pointer: UnsafeMutableRawPointer) { + Unmanaged.fromOpaque(pointer).release() +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_closure_unregister") +internal func _swift_js_closure_unregister(_ id: Int32) +#else +/// Unregisters a Swift closure from the FinalizationRegistry +/// +/// - Parameter id: The JavaScriptObjectRef of the JS closure object created by +/// the BridgeJS's `make_swift_closure_{signature}` function. +/// +/// - Note: This is a best-effort operation. +/// According to the ECMAScript specification, calling +/// `FinalizationRegistry.prototype.unregister` does not guarantee that +/// a finalization callback will be suppressed if the target object has +/// already been garbage-collected and cleanup has been scheduled. +/// This means that the finalization callback should be tolerant of the +/// object being already collected. +/// See: https://tc39.es/ecma262/multipage/managing-memory.html#sec-finalization-registry.prototype.unregister +internal func _swift_js_closure_unregister(_ id: Int32) { + _onlyAvailableOnWasm() +} +#endif + // MARK: Type lowering/lifting // // The following part defines the parameter and return value lowering/lifting @@ -1108,6 +1142,21 @@ extension UnsafeMutablePointer: _BridgedSwiftStackType { } } +// Optional support for JSTypedClosure +extension Optional { + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> ( + isSome: Int32, value: Int32 + ) where Wrapped == JSTypedClosure { + switch consume self { + case .none: + return (isSome: 0, value: 0) + case .some(let wrapped): + // Use return lowering to retain the JS function so JS lifting can fetch it from the heap. + return (isSome: 1, value: wrapped.bridgeJSLowerParameter()) + } + } +} + extension Optional where Wrapped == Bool { // MARK: ExportSwift diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSClosure.swift b/Sources/JavaScriptKit/FundamentalObjects/JSClosure.swift index 941b3f46..b3e80e66 100644 --- a/Sources/JavaScriptKit/FundamentalObjects/JSClosure.swift +++ b/Sources/JavaScriptKit/FundamentalObjects/JSClosure.swift @@ -245,6 +245,97 @@ public class JSClosure: JSObject, JSClosureProtocol { #endif } +/// Heap storage for typed closures generated by BridgeJS. +/// +/// The storage is owned by the JavaScript closure and keeps the call-site metadata +/// so that calls after `release()` can report a helpful error. +@_spi(BridgeJS) public final class _BridgeJSTypedClosureBox: _BridgedSwiftClosureBox { + @_spi(BridgeJS) public var closure: Signature + var isManuallyReleased: Bool = false + + init(_ closure: Signature) { + self.closure = closure + } +} + +/// A typed handle to a JavaScript closure generated by BridgeJS. +/// +/// Use `JSTypedClosure` when you need to pass a Swift closure to JavaScript and then +/// manage its lifetime explicitly from Swift. You must call `release()` when the closure +/// is no longer needed. After releasing, any attempt to invoke the closure from JavaScript +/// throws a `JSException` (no crash), including a file/line message pointing to where the +/// typed closure was created. +/// +/// The underlying JavaScript function is also registered with a `FinalizationRegistry` as a +/// safety net to release the Swift closure storage if `release()` is forgotten, but this +/// is non-deterministic and should not be relied on for timely cleanup. +/// +/// ```swift +/// @JSFunction func someJSFunction(_ c: JSTypedClosure<(Int) -> Int>) throws(JSException) +/// let closure = JSTypedClosure<(Int) -> Int> { $0 + 1 } +/// defer { closure.release() } +/// try someJSFunction(closure) +/// ``` +public struct JSTypedClosure { + private let storage: _BridgeJSTypedClosureBox + private let _jsObject: JSObject + + @_spi(BridgeJS) + public init( + makeClosure: (_ pointer: UnsafeMutableRawPointer, _ fileID: UnsafePointer, _ line: UInt32) -> Int32, + body: Signature, + fileID: StaticString, + line: UInt32 + ) { + let storage = _BridgeJSTypedClosureBox(body) + // NOTE: Perform an unbalanced retain to give the closure box storage ownership + // to the JavaScript side. It will be balanced by two code paths: + // + // 1. When the JS closure made by `makeClosure` is GC'ed, the FinalizationRegistry + // will call `_bjs_release_swift_closure` to release the closure box storage. + // 2. When Swift side manually calls `release()` on the closure, it will release + // the closure box storage. + let pointer = Unmanaged.passRetained(storage).toOpaque() + let id = makeClosure(pointer, fileID.utf8Start, line) + self._jsObject = JSObject(id: UInt32(bitPattern: id)) + self.storage = storage + } + + @_spi(BridgeJS) + public func bridgeJSLowerParameter() -> Int32 { + return _jsObject.bridgeJSLowerParameter() + } + + @_spi(BridgeJS) + public func bridgeJSLowerReturn() -> Int32 { + return _jsObject.bridgeJSLowerReturn() + } + + /// The underlying JavaScript function handle. + /// + /// Use this when you need to store or compare the JS function identity on the JavaScript side. + public var jsObject: JSObject { _jsObject } + + /// Releases the Swift closure storage owned by this typed closure. + /// + /// Call this exactly once when the closure is no longer needed by JavaScript. + /// After release, any attempt to invoke the closure from JavaScript throws a `JSException` + /// describing a call on a released `JSTypedClosure`. + /// Calling `release()` multiple times has no effect. + public func release() { + guard !storage.isManuallyReleased else { + // Already manually released + return + } + storage.isManuallyReleased = true + // Unregister the closure from the FinalizationRegistry because we here decrement + // the refcount of the storage, so the finalizer won't be responsible for releasing it. + _swift_js_closure_unregister(Int32(bitPattern: _jsObject.id)) + // Balance the retain given to the JavaScript side + Unmanaged.passUnretained(storage).release() + } +} + #if compiler(>=5.5) && (!hasFeature(Embedded) || os(WASI)) @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) private func makeAsyncClosure( diff --git a/Tests/BridgeJSRuntimeTests/ClosureSupportTests.swift b/Tests/BridgeJSRuntimeTests/ClosureSupportTests.swift new file mode 100644 index 00000000..320fec52 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/ClosureSupportTests.swift @@ -0,0 +1,290 @@ +import XCTest +@_spi(Experimental) import JavaScriptKit + +@JSClass struct ClosureSupportImports { + + @JSFunction static func jsApplyVoid(_ callback: JSTypedClosure<() -> Void>) throws(JSException) + @JSFunction static func jsApplyBool(_ callback: JSTypedClosure<() -> Bool>) throws(JSException) -> Bool + @JSFunction static func jsApplyInt( + _ value: Int, + _ transform: JSTypedClosure<(Int) -> Int> + ) throws(JSException) -> Int + @JSFunction static func jsApplyDouble( + _ value: Double, + _ transform: JSTypedClosure<(Double) -> Double> + ) throws(JSException) -> Double + @JSFunction static func jsApplyString( + _ value: String, + _ transform: JSTypedClosure<(String) -> String> + ) throws(JSException) -> String + // @JSFunction static func jsApplyJSValue( + // _ value: JSValue, + // _ transform: JSTypedClosure<(JSValue) -> JSValue> + // ) throws(JSException) -> JSValue + @JSFunction static func jsApplyJSObject( + _ value: JSObject, + _ transform: JSTypedClosure<(JSObject) -> JSObject> + ) throws(JSException) -> JSObject + // @JSFunction static func jsApplyArrayInt( + // _ value: [Int], + // _ transform: JSTypedClosure<([Int]) -> [Int]> + // ) throws(JSException) -> [Int] + // @JSFunction static func jsApplyArrayDouble( + // _ value: [Double], + // _ transform: JSTypedClosure<([Double]) -> [Double]> + // ) throws(JSException) -> [Double] + // @JSFunction static func jsApplyArrayString( + // _ value: [String], + // _ transform: JSTypedClosure<([String]) -> [String]> + // ) throws(JSException) -> [String] + // @JSFunction static func jsApplyArrayJSValue( + // _ value: [JSValue], + // _ transform: JSTypedClosure<([JSValue]) -> [JSValue]> + // ) throws(JSException) -> [JSValue] + // @JSFunction static func jsApplyArrayJSObject( + // _ value: [JSObject], + // _ transform: JSTypedClosure<([JSObject]) -> [JSObject]> + // ) throws(JSException) -> [JSObject] + + @JSFunction static func jsMakeIntToInt(_ base: Int) throws(JSException) -> (Int) -> Int + @JSFunction static func jsMakeDoubleToDouble(_ base: Double) throws(JSException) -> (Double) -> Double + @JSFunction static func jsMakeStringToString(_ `prefix`: String) throws(JSException) -> (String) -> String + + @JSFunction static func jsCallTwice( + _ value: Int, + _ callback: JSTypedClosure<(Int) -> Void> + ) throws(JSException) -> Int + @JSFunction static func jsCallBinary(_ callback: JSTypedClosure<(Int, Int) -> Int>) throws(JSException) -> Int + @JSFunction static func jsCallTriple(_ callback: JSTypedClosure<(Int, Int, Int) -> Int>) throws(JSException) -> Int + @JSFunction static func jsCallAfterRelease(_ callback: JSTypedClosure<() -> Void>) throws(JSException) -> String + @JSFunction static func jsOptionalInvoke(_ callback: JSTypedClosure<() -> Bool>?) throws(JSException) -> Bool + @JSFunction static func jsStoreClosure(_ callback: JSTypedClosure<() -> Void>) throws(JSException) + @JSFunction static func jsCallStoredClosure() throws(JSException) + @JSFunction static func jsHeapCount() throws(JSException) -> Int + + @JSFunction static func runJsClosureSupportTests() throws(JSException) +} + +@JS class ClosureSupportExports { + @JS static func makeIntToInt(_ base: Int) -> (Int) -> Int { + return { $0 + base } + } + @JS static func makeDoubleToDouble(_ base: Double) -> (Double) -> Double { + return { $0 + base } + } + @JS static func makeStringToString(_ prefix: String) -> (String) -> String { + return { prefix + $0 } + } + + @JS static func makeJSIntToInt(_ base: Int) -> JSTypedClosure<(Int) -> Int> { + return JSTypedClosure { $0 + base } + } + @JS static func makeJSDoubleToDouble(_ base: Double) -> JSTypedClosure<(Double) -> Double> { + return JSTypedClosure { $0 + base } + } + @JS static func makeJSStringToString(_ prefix: String) -> JSTypedClosure<(String) -> String> { + return JSTypedClosure { prefix + $0 } + } +} + +final class ClosureSupportTests: XCTestCase { + + func testRunJsClosureSupportTests() throws { + try ClosureSupportImports.runJsClosureSupportTests() + } + + func testClosureParameterVoidToVoid() throws { + var called = false + let transform = JSTypedClosure<() -> Void> { + called = true + } + defer { transform.release() } + try ClosureSupportImports.jsApplyVoid(transform) + XCTAssertTrue(called) + } + + func testClosureParameterBoolToBool() throws { + let transform = JSTypedClosure<() -> Bool> { true } + defer { transform.release() } + let result = try ClosureSupportImports.jsApplyBool(transform) + XCTAssertTrue(result) + } + + func testClosureParameterIntToInt() throws { + let transform = JSTypedClosure { $0 * 2 } + defer { transform.release() } + let result = try ClosureSupportImports.jsApplyInt(21, transform) + XCTAssertEqual(result, 42) + } + + func testClosureParameterDoubleToDouble() throws { + let transform = JSTypedClosure<(Double) -> Double> { $0 * 2 } + defer { transform.release() } + let result = try ClosureSupportImports.jsApplyDouble(21.0, transform) + XCTAssertEqual(result, 42.0) + } + + func testClosureParameterStringToString() throws { + let transform = JSTypedClosure { (value: String) in + value + ", world!" + } + defer { transform.release() } + let result = try ClosureSupportImports.jsApplyString("Hello", transform) + XCTAssertEqual(result, "Hello, world!") + } + + // func testClosureParameterJSValueToJSValue() throws { + // let transform = JSTypedClosure<(JSValue) -> JSValue> { $0 } + // defer { transform.release() } + // let result = try JSTypedClosureImports.jsApplyJSValue(.number(1), transform) + // XCTAssertEqual(result, .number(1)) + // } + + func testClosureParameterJSObjectToJSObject() throws { + let transform = JSTypedClosure<(JSObject) -> JSObject> { $0 } + defer { transform.release() } + let obj = JSObject() + let result = try ClosureSupportImports.jsApplyJSObject(obj, transform) + XCTAssertEqual(result, obj) + } + + // func testClosureParameterArrayIntToArrayInt() throws { + // let transform = JSTypedClosure<([Int]) -> [Int]> { $0 } + // defer { transform.release() } + // let result = try ClosureSupportImports.jsApplyArrayInt([1, 2, 3], transform) + // XCTAssertEqual(result, [1, 2, 3]) + // } + + // func testClosureParameterArrayDoubleToArrayDouble() throws { + // let transform = JSTypedClosure<([Double]) -> [Double]> { $0 } + // defer { transform.release() } + // let result = try ClosureSupportImports.jsApplyArrayDouble([1.0, 2.0, 3.0], transform) + // XCTAssertEqual(result, [1.0, 2.0, 3.0]) + // } + + // func testClosureParameterArrayStringToArrayString() throws { + // let transform = JSTypedClosure<([String]) -> [String]> { $0 } + // defer { transform.release() } + // let result = try ClosureSupportImports.jsApplyArrayString(["a", "b", "c"], transform) + // XCTAssertEqual(result, ["a", "b", "c"]) + // } + + // func testClosureParameterArrayJSValueToArrayJSValue() throws { + // let transform = JSTypedClosure<([JSValue]) -> [JSValue]> { $0 } + // defer { transform.release() } + // let result = try ClosureSupportImports.jsApplyArrayJSValue([.number(1), .number(2), .number(3)], transform) + // XCTAssertEqual(result, [.number(1), .number(2), .number(3)]) + // } + + // func testClosureParameterArrayJSObjectToArrayJSObject() throws { + // let transform = JSTypedClosure<([JSObject]) -> [JSObject]> { $0 } + // defer { transform.release() } + // let obj1 = JSObject() + // let obj2 = JSObject() + // let obj3 = JSObject() + // let result = try ClosureSupportImports.jsApplyArrayJSObject([obj1, obj2, obj3], transform) + // XCTAssertEqual(result, [obj1, obj2, obj3]) + // } + + func testClosureReturnIntToInt() throws { + let c = try ClosureSupportImports.jsMakeIntToInt(10) + XCTAssertEqual(c(0), 10) + XCTAssertEqual(c(32), 42) + } + + func testClosureReturnDoubleToDouble() throws { + let c = try ClosureSupportImports.jsMakeDoubleToDouble(10.0) + XCTAssertEqual(c(0.0), 10.0) + XCTAssertEqual(c(32.0), 42.0) + } + + func testClosureReturnStringToString() throws { + let c = try ClosureSupportImports.jsMakeStringToString("Hello, ") + XCTAssertEqual(c("world!"), "Hello, world!") + } + + func testClosureParameterIntToVoid() throws { + var total = 0 + let callback = JSTypedClosure<(Int) -> Void> { value in + total += value + } + defer { callback.release() } + let ret = try ClosureSupportImports.jsCallTwice(5, callback) + XCTAssertEqual(ret, 5) + XCTAssertEqual(total, 10) + } + + func testCallingReleasedClosureThrows() { + let transform = JSTypedClosure<(Int) -> Int> { $0 + 1 } + transform.release() + + do { + _ = try ClosureSupportImports.jsApplyInt(41, transform) + XCTFail("Expected JSException for released closure") + } catch let error { + let message = error.thrownValue.object?["message"].string + XCTAssertNotNil(message) + XCTAssertTrue(message?.contains(#fileID) ?? false, "message=\(message ?? "nil")") + } + } + + func testMultipleArity() throws { + let sum = JSTypedClosure<(Int, Int) -> Int> { $0 + $1 } + defer { sum.release() } + XCTAssertEqual(try ClosureSupportImports.jsCallBinary(sum), 3) + } + + func testTripleArity() throws { + let sum = JSTypedClosure<(Int, Int, Int) -> Int> { $0 + $1 + $2 } + defer { sum.release() } + XCTAssertEqual(try ClosureSupportImports.jsCallTriple(sum), 6) + } + + func testOptionalNoneSkipsCall() throws { + XCTAssertFalse(try ClosureSupportImports.jsOptionalInvoke(nil)) + } + + func testOptionalSomeCalls() throws { + var called = false + let closure = JSTypedClosure<() -> Bool> { + called = true + return true + } + defer { closure.release() } + XCTAssertTrue(try ClosureSupportImports.jsOptionalInvoke(closure)) + XCTAssertTrue(called) + } + + func testDropDuringCallThenThrows() throws { + var closure: JSTypedClosure<() -> Void>! = nil + closure = JSTypedClosure { + closure.release() + } + let message = try ClosureSupportImports.jsCallAfterRelease(closure) + XCTAssertTrue( + message.contains(#fileID), + "\"\(message)\" does not contain expected file name" + ) + } + + func testStoredClosureAfterReleaseThrows() throws { + let closure = JSTypedClosure<() -> Void> {} + try ClosureSupportImports.jsStoreClosure(closure) + closure.release() + XCTAssertThrowsError(try ClosureSupportImports.jsCallStoredClosure()) + } + + func testClosuresDoNotLeakHeapEntries() throws { + let baseline = try ClosureSupportImports.jsHeapCount() + + for _ in 0..<50 { + let closure: JSTypedClosure<(Int) -> Void> = JSTypedClosure { _ in } + _ = try? ClosureSupportImports.jsCallTwice(0, closure) + } + + // Trigger GC and read heap size from JS side + let after = try ClosureSupportImports.jsHeapCount() + XCTAssertEqual(after, baseline, "Heap entry count should return to baseline after GC") + } + +} diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index 7ca92b35..163c9e47 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -16,18 +16,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests1 } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTests10HttpStatusO_Si: _BridgedSwiftClosureBox { - let closure: (HttpStatus) -> Int - init(_ closure: @escaping (HttpStatus) -> Int) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTests10HttpStatusO_Si { - static func bridgeJSLower(_ closure: @escaping (HttpStatus) -> Int) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTests10HttpStatusO_Si(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (HttpStatus) -> Int { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -43,12 +41,23 @@ private enum _BJS_Closure_20BridgeJSRuntimeTests10HttpStatusO_Si { } } +extension JSTypedClosure where Signature == (HttpStatus) -> Int { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (HttpStatus) -> Int) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTests10HttpStatusO_Si>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(HttpStatus.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(HttpStatus) -> Int>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(HttpStatus.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -64,18 +73,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5 } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTests5ThemeO_SS: _BridgedSwiftClosureBox { - let closure: (Theme) -> String - init(_ closure: @escaping (Theme) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTests5ThemeO_SS { - static func bridgeJSLower(_ closure: @escaping (Theme) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTests5ThemeO_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Theme) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -91,12 +98,23 @@ private enum _BJS_Closure_20BridgeJSRuntimeTests5ThemeO_SS { } } +extension JSTypedClosure where Signature == (Theme) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Theme) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTests5ThemeO_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Theme.bridgeJSLiftParameter(param0Bytes, param0Length)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Theme) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Theme.bridgeJSLiftParameter(param0Bytes, param0Length)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -112,18 +130,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5 } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTests5ThemeO_Sb: _BridgedSwiftClosureBox { - let closure: (Theme) -> Bool - init(_ closure: @escaping (Theme) -> Bool) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTests5ThemeO_Sb { - static func bridgeJSLower(_ closure: @escaping (Theme) -> Bool) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTests5ThemeO_Sb(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Theme) -> Bool { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -139,12 +155,23 @@ private enum _BJS_Closure_20BridgeJSRuntimeTests5ThemeO_Sb { } } +extension JSTypedClosure where Signature == (Theme) -> Bool { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Theme) -> Bool) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTests5ThemeO_Sb>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Theme.bridgeJSLiftParameter(param0Bytes, param0Length)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Theme) -> Bool>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Theme.bridgeJSLiftParameter(param0Bytes, param0Length)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -160,18 +187,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7 } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTests7GreeterC_SS: _BridgedSwiftClosureBox { - let closure: (Greeter) -> String - init(_ closure: @escaping (Greeter) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTests7GreeterC_SS { - static func bridgeJSLower(_ closure: @escaping (Greeter) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTests7GreeterC_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Greeter) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -187,12 +212,80 @@ private enum _BJS_Closure_20BridgeJSRuntimeTests7GreeterC_SS { } } +extension JSTypedClosure where Signature == (Greeter) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Greeter) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTests7GreeterC_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Greeter.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Greeter) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Greeter.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC { + static func bridgeJSLift(_ callbackId: Int32) -> (JSObject) -> JSObject { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC(callbackValue, param0Value) + return JSObject.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (JSObject) -> JSObject { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (JSObject) -> JSObject) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(JSObject) -> JSObject>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(JSObject.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -208,18 +301,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9 } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTests9APIResultO_SS: _BridgedSwiftClosureBox { - let closure: (APIResult) -> String - init(_ closure: @escaping (APIResult) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTests9APIResultO_SS { - static func bridgeJSLower(_ closure: @escaping (APIResult) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTests9APIResultO_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (APIResult) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -235,12 +326,23 @@ private enum _BJS_Closure_20BridgeJSRuntimeTests9APIResultO_SS { } } +extension JSTypedClosure where Signature == (APIResult) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (APIResult) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTests9APIResultO_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(APIResult.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(APIResult) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(APIResult.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -256,18 +358,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9 } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTests9DirectionO_SS: _BridgedSwiftClosureBox { - let closure: (Direction) -> String - init(_ closure: @escaping (Direction) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTests9DirectionO_SS { - static func bridgeJSLower(_ closure: @escaping (Direction) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTests9DirectionO_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Direction) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -283,12 +383,23 @@ private enum _BJS_Closure_20BridgeJSRuntimeTests9DirectionO_SS { } } +extension JSTypedClosure where Signature == (Direction) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Direction) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTests9DirectionO_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Direction.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Direction) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Direction.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -304,18 +415,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9 } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTests9DirectionO_Sb: _BridgedSwiftClosureBox { - let closure: (Direction) -> Bool - init(_ closure: @escaping (Direction) -> Bool) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTests9DirectionO_Sb { - static func bridgeJSLower(_ closure: @escaping (Direction) -> Bool) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTests9DirectionO_Sb(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Direction) -> Bool { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -331,12 +440,23 @@ private enum _BJS_Closure_20BridgeJSRuntimeTests9DirectionO_Sb { } } +extension JSTypedClosure where Signature == (Direction) -> Bool { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Direction) -> Bool) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTests9DirectionO_Sb>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Direction.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Direction) -> Bool>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Direction.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -352,18 +472,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsS } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTestsSS_7GreeterC: _BridgedSwiftClosureBox { - let closure: (String) -> Greeter - init(_ closure: @escaping (String) -> Greeter) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTestsSS_7GreeterC { - static func bridgeJSLower(_ closure: @escaping (String) -> Greeter) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTestsSS_7GreeterC(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (String) -> Greeter { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -379,12 +497,23 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSS_7GreeterC { } } +extension JSTypedClosure where Signature == (String) -> Greeter { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (String) -> Greeter) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> UnsafeMutableRawPointer { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTestsSS_7GreeterC>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(String.bridgeJSLiftParameter(param0Bytes, param0Length)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(String) -> Greeter>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(String.bridgeJSLiftParameter(param0Bytes, param0Length)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -400,18 +529,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsS } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTestsSS_SS: _BridgedSwiftClosureBox { - let closure: (String) -> String - init(_ closure: @escaping (String) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTestsSS_SS { - static func bridgeJSLower(_ closure: @escaping (String) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTestsSS_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (String) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -427,12 +554,80 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSS_SS { } } +extension JSTypedClosure where Signature == (String) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (String) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTestsSS_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(String.bridgeJSLiftParameter(param0Bytes, param0Length)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(String) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(String.bridgeJSLiftParameter(param0Bytes, param0Length)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd(_ callback: Int32, _ param0: Float64) -> Float64 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd(_ callback: Int32, _ param0: Float64) -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSd_Sd { + static func bridgeJSLift(_ callbackId: Int32) -> (Double) -> Double { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd(callbackValue, param0Value) + return Double.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Double) -> Double { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Double) -> Double) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd(_ boxPtr: UnsafeMutableRawPointer, _ param0: Float64) -> Float64 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Double) -> Double>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Double.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -448,18 +643,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsS } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTestsSiSSSd_SS: _BridgedSwiftClosureBox { - let closure: (Int, String, Double) -> String - init(_ closure: @escaping (Int, String, Double) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTestsSiSSSd_SS { - static func bridgeJSLower(_ closure: @escaping (Int, String, Double) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTestsSiSSSd_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Int, String, Double) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0, param1, param2 in @@ -477,12 +670,140 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSiSSSd_SS { } } +extension JSTypedClosure where Signature == (Int, String, Double) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Int, String, Double) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32, _ param1Bytes: Int32, _ param1Length: Int32, _ param2: Float64) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTestsSiSSSd_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Int.bridgeJSLiftParameter(param0), String.bridgeJSLiftParameter(param1Bytes, param1Length), Double.bridgeJSLiftParameter(param2)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Int, String, Double) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Int.bridgeJSLiftParameter(param0), String.bridgeJSLiftParameter(param1Bytes, param1Length), Double.bridgeJSLiftParameter(param2)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si(_ callback: Int32, _ param0: Int32, _ param1: Int32, _ param2: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si(_ callback: Int32, _ param0: Int32, _ param1: Int32, _ param2: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSiSiSi_Si { + static func bridgeJSLift(_ callbackId: Int32) -> (Int, Int, Int) -> Int { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0, param1, param2 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let param1Value = param1.bridgeJSLowerParameter() + let param2Value = param2.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si(callbackValue, param0Value, param1Value, param2Value) + return Int.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Int, Int, Int) -> Int { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Int, Int, Int) -> Int) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32, _ param1: Int32, _ param2: Int32) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Int, Int, Int) -> Int>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Int.bridgeJSLiftParameter(param0), Int.bridgeJSLiftParameter(param1), Int.bridgeJSLiftParameter(param2)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si(_ callback: Int32, _ param0: Int32, _ param1: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si(_ callback: Int32, _ param0: Int32, _ param1: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSiSi_Si { + static func bridgeJSLift(_ callbackId: Int32) -> (Int, Int) -> Int { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0, param1 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let param1Value = param1.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si(callbackValue, param0Value, param1Value) + return Int.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Int, Int) -> Int { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Int, Int) -> Int) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32, _ param1: Int32) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Int, Int) -> Int>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Int.bridgeJSLiftParameter(param0), Int.bridgeJSLiftParameter(param1)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -498,18 +819,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsS } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTestsSi_Si: _BridgedSwiftClosureBox { - let closure: (Int) -> Int - init(_ closure: @escaping (Int) -> Int) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTestsSi_Si { - static func bridgeJSLower(_ closure: @escaping (Int) -> Int) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTestsSi_Si(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Int) -> Int { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -525,12 +844,23 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSi_Si { } } +extension JSTypedClosure where Signature == (Int) -> Int { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Int) -> Int) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTestsSi_Si>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Int.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Int) -> Int>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Int.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -546,18 +876,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsS } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTestsSi_y: _BridgedSwiftClosureBox { - let closure: (Int) -> Void - init(_ closure: @escaping (Int) -> Void) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTestsSi_y { - static func bridgeJSLower(_ closure: @escaping (Int) -> Void) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTestsSi_y(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Int) -> Void { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -572,12 +900,23 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSi_y { } } +extension JSTypedClosure where Signature == (Int) -> Void { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Int) -> Void) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTestsSi_y>.fromOpaque(boxPtr).takeUnretainedValue() - box.closure(Int.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Int) -> Void>>.fromOpaque(boxPtr).takeUnretainedValue().closure + closure(Int.bridgeJSLiftParameter(param0)) #else fatalError("Only available on WebAssembly") #endif @@ -592,18 +931,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsS } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTestsSq5ThemeO_SS: _BridgedSwiftClosureBox { - let closure: (Optional) -> String - init(_ closure: @escaping (Optional) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTestsSq5ThemeO_SS { - static func bridgeJSLower(_ closure: @escaping (Optional) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTestsSq5ThemeO_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -619,12 +956,23 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSq5ThemeO_SS { } } -@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS") -@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS") +extension JSTypedClosure where Signature == (Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTestsSq5ThemeO_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Bytes, param0Length)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Bytes, param0Length)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -640,18 +988,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsS } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTestsSq7GreeterC_SS: _BridgedSwiftClosureBox { - let closure: (Optional) -> String - init(_ closure: @escaping (Optional) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTestsSq7GreeterC_SS { - static func bridgeJSLower(_ closure: @escaping (Optional) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTestsSq7GreeterC_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -667,12 +1013,23 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSq7GreeterC_SS { } } +extension JSTypedClosure where Signature == (Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTestsSq7GreeterC_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -688,18 +1045,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsS } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC: _BridgedSwiftClosureBox { - let closure: (Optional) -> Optional - init(_ closure: @escaping (Optional) -> Optional) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC { - static func bridgeJSLower(_ closure: @escaping (Optional) -> Optional) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -715,12 +1070,23 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC { } } +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -736,18 +1102,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsS } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTestsSq9APIResultO_SS: _BridgedSwiftClosureBox { - let closure: (Optional) -> String - init(_ closure: @escaping (Optional) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTestsSq9APIResultO_SS { - static func bridgeJSLower(_ closure: @escaping (Optional) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTestsSq9APIResultO_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -763,12 +1127,23 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSq9APIResultO_SS { } } +extension JSTypedClosure where Signature == (Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTestsSq9APIResultO_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Optional.bridgeJSLiftParameter(param0IsSome, param0CaseId)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0CaseId)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -784,18 +1159,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsS } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTestsSq9DirectionO_SS: _BridgedSwiftClosureBox { - let closure: (Optional) -> String - init(_ closure: @escaping (Optional) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTestsSq9DirectionO_SS { - static func bridgeJSLower(_ closure: @escaping (Optional) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTestsSq9DirectionO_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -811,12 +1184,23 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSq9DirectionO_SS { } } +extension JSTypedClosure where Signature == (Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTestsSq9DirectionO_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -832,18 +1216,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsS } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTestsSqSS_SS: _BridgedSwiftClosureBox { - let closure: (Optional) -> String - init(_ closure: @escaping (Optional) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTestsSqSS_SS { - static func bridgeJSLower(_ closure: @escaping (Optional) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTestsSqSS_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -859,12 +1241,23 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSqSS_SS { } } +extension JSTypedClosure where Signature == (Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTestsSqSS_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Bytes, param0Length)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Bytes, param0Length)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -880,18 +1273,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsS } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTestsSqSi_SS: _BridgedSwiftClosureBox { - let closure: (Optional) -> String - init(_ closure: @escaping (Optional) -> String) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTestsSqSi_SS { - static func bridgeJSLower(_ closure: @escaping (Optional) -> String) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTestsSqSi_SS(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in @@ -907,12 +1298,79 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSqSi_SS { } } +extension JSTypedClosure where Signature == (Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTestsSqSi_SS>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb(_ callback: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb(_ callback: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsy_Sb { + static func bridgeJSLift(_ callbackId: Int32) -> () -> Bool { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb(callbackValue) + return Bool.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == () -> Bool { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping () -> Bool) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb(_ boxPtr: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<() -> Bool>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure() return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -928,18 +1386,16 @@ fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy } #endif -private final class _BJS_ClosureBox_20BridgeJSRuntimeTestsy_Sq7GreeterC: _BridgedSwiftClosureBox { - let closure: () -> Optional - init(_ closure: @escaping () -> Optional) { - self.closure = closure - } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif private enum _BJS_Closure_20BridgeJSRuntimeTestsy_Sq7GreeterC { - static func bridgeJSLower(_ closure: @escaping () -> Optional) -> UnsafeMutableRawPointer { - let box = _BJS_ClosureBox_20BridgeJSRuntimeTestsy_Sq7GreeterC(closure) - return Unmanaged.passRetained(box).toOpaque() - } static func bridgeJSLift(_ callbackId: Int32) -> () -> Optional { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] in @@ -954,18 +1410,83 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsy_Sq7GreeterC { } } +extension JSTypedClosure where Signature == () -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping () -> Optional) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC, + body: body, + fileID: fileID, + line: line + ) + } +} + @_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC") @_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC") public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC(_ boxPtr: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let box = Unmanaged<_BJS_ClosureBox_20BridgeJSRuntimeTestsy_Sq7GreeterC>.fromOpaque(boxPtr).takeUnretainedValue() - let result = box.closure() + let closure = Unmanaged<_BridgeJSTypedClosureBox<() -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure() return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y(_ callback: Int32) -> Void +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y(_ callback: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsy_y { + static func bridgeJSLift(_ callbackId: Int32) -> () -> Void { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y(callbackValue) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == () -> Void { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping () -> Void) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y(_ boxPtr: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<() -> Void>>.fromOpaque(boxPtr).takeUnretainedValue().closure + closure() + #else + fatalError("Only available on WebAssembly") + #endif +} + struct AnyDataProcessor: DataProcessor, _BridgedSwiftProtocolWrapper { let jsObject: JSObject @@ -4934,10 +5455,10 @@ public func _bjs_formatName(_ nameBytes: Int32, _ nameLength: Int32, _ transform @_expose(wasm, "bjs_makeFormatter") @_cdecl("bjs_makeFormatter") -public func _bjs_makeFormatter(_ prefixBytes: Int32, _ prefixLength: Int32) -> UnsafeMutableRawPointer { +public func _bjs_makeFormatter(_ prefixBytes: Int32, _ prefixLength: Int32) -> Int32 { #if arch(wasm32) let ret = makeFormatter(prefix: String.bridgeJSLiftParameter(prefixBytes, prefixLength)) - return _BJS_Closure_20BridgeJSRuntimeTestsSS_SS.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -4945,10 +5466,10 @@ public func _bjs_makeFormatter(_ prefixBytes: Int32, _ prefixLength: Int32) -> U @_expose(wasm, "bjs_makeAdder") @_cdecl("bjs_makeAdder") -public func _bjs_makeAdder(_ base: Int32) -> UnsafeMutableRawPointer { +public func _bjs_makeAdder(_ base: Int32) -> Int32 { #if arch(wasm32) let ret = makeAdder(base: Int.bridgeJSLiftParameter(base)) - return _BJS_Closure_20BridgeJSRuntimeTestsSi_Si.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -6081,6 +6602,97 @@ public func _bjs_arrayMembersFirst() -> Void { #endif } +@_expose(wasm, "bjs_ClosureSupportExports_static_makeIntToInt") +@_cdecl("bjs_ClosureSupportExports_static_makeIntToInt") +public func _bjs_ClosureSupportExports_static_makeIntToInt(_ base: Int32) -> Int32 { + #if arch(wasm32) + let ret = ClosureSupportExports.makeIntToInt(_: Int.bridgeJSLiftParameter(base)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClosureSupportExports_static_makeDoubleToDouble") +@_cdecl("bjs_ClosureSupportExports_static_makeDoubleToDouble") +public func _bjs_ClosureSupportExports_static_makeDoubleToDouble(_ base: Float64) -> Int32 { + #if arch(wasm32) + let ret = ClosureSupportExports.makeDoubleToDouble(_: Double.bridgeJSLiftParameter(base)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClosureSupportExports_static_makeStringToString") +@_cdecl("bjs_ClosureSupportExports_static_makeStringToString") +public func _bjs_ClosureSupportExports_static_makeStringToString(_ prefixBytes: Int32, _ prefixLength: Int32) -> Int32 { + #if arch(wasm32) + let ret = ClosureSupportExports.makeStringToString(_: String.bridgeJSLiftParameter(prefixBytes, prefixLength)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClosureSupportExports_static_makeJSIntToInt") +@_cdecl("bjs_ClosureSupportExports_static_makeJSIntToInt") +public func _bjs_ClosureSupportExports_static_makeJSIntToInt(_ base: Int32) -> Int32 { + #if arch(wasm32) + let ret = ClosureSupportExports.makeJSIntToInt(_: Int.bridgeJSLiftParameter(base)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClosureSupportExports_static_makeJSDoubleToDouble") +@_cdecl("bjs_ClosureSupportExports_static_makeJSDoubleToDouble") +public func _bjs_ClosureSupportExports_static_makeJSDoubleToDouble(_ base: Float64) -> Int32 { + #if arch(wasm32) + let ret = ClosureSupportExports.makeJSDoubleToDouble(_: Double.bridgeJSLiftParameter(base)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClosureSupportExports_static_makeJSStringToString") +@_cdecl("bjs_ClosureSupportExports_static_makeJSStringToString") +public func _bjs_ClosureSupportExports_static_makeJSStringToString(_ prefixBytes: Int32, _ prefixLength: Int32) -> Int32 { + #if arch(wasm32) + let ret = ClosureSupportExports.makeJSStringToString(_: String.bridgeJSLiftParameter(prefixBytes, prefixLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClosureSupportExports_deinit") +@_cdecl("bjs_ClosureSupportExports_deinit") +public func _bjs_ClosureSupportExports_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension ClosureSupportExports: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_ClosureSupportExports_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportExports_wrap") +fileprivate func _bjs_ClosureSupportExports_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_ClosureSupportExports_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + @_expose(wasm, "bjs_Greeter_init") @_cdecl("bjs_Greeter_init") public func _bjs_Greeter_init(_ nameBytes: Int32, _ nameLength: Int32) -> UnsafeMutableRawPointer { @@ -6126,10 +6738,10 @@ public func _bjs_Greeter_greetWith(_ _self: UnsafeMutableRawPointer, _ greeter: @_expose(wasm, "bjs_Greeter_makeFormatter") @_cdecl("bjs_Greeter_makeFormatter") -public func _bjs_Greeter_makeFormatter(_ _self: UnsafeMutableRawPointer, _ suffixBytes: Int32, _ suffixLength: Int32) -> UnsafeMutableRawPointer { +public func _bjs_Greeter_makeFormatter(_ _self: UnsafeMutableRawPointer, _ suffixBytes: Int32, _ suffixLength: Int32) -> Int32 { #if arch(wasm32) let ret = Greeter.bridgeJSLiftParameter(_self).makeFormatter(suffix: String.bridgeJSLiftParameter(suffixBytes, suffixLength)) - return _BJS_Closure_20BridgeJSRuntimeTestsSS_SS.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -6137,10 +6749,10 @@ public func _bjs_Greeter_makeFormatter(_ _self: UnsafeMutableRawPointer, _ suffi @_expose(wasm, "bjs_Greeter_static_makeCreator") @_cdecl("bjs_Greeter_static_makeCreator") -public func _bjs_Greeter_static_makeCreator(_ defaultNameBytes: Int32, _ defaultNameLength: Int32) -> UnsafeMutableRawPointer { +public func _bjs_Greeter_static_makeCreator(_ defaultNameBytes: Int32, _ defaultNameLength: Int32) -> Int32 { #if arch(wasm32) let ret = Greeter.makeCreator(defaultName: String.bridgeJSLiftParameter(defaultNameBytes, defaultNameLength)) - return _BJS_Closure_20BridgeJSRuntimeTestsSS_7GreeterC.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -6148,10 +6760,10 @@ public func _bjs_Greeter_static_makeCreator(_ defaultNameBytes: Int32, _ default @_expose(wasm, "bjs_Greeter_makeCustomGreeter") @_cdecl("bjs_Greeter_makeCustomGreeter") -public func _bjs_Greeter_makeCustomGreeter(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +public func _bjs_Greeter_makeCustomGreeter(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) let ret = Greeter.bridgeJSLiftParameter(_self).makeCustomGreeter() - return _BJS_Closure_20BridgeJSRuntimeTests7GreeterC_SS.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -7981,10 +8593,10 @@ public func _bjs_TextProcessor_processWithCustom(_ _self: UnsafeMutableRawPointe @_expose(wasm, "bjs_TextProcessor_getTransform") @_cdecl("bjs_TextProcessor_getTransform") -public func _bjs_TextProcessor_getTransform(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +public func _bjs_TextProcessor_getTransform(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) let ret = TextProcessor.bridgeJSLiftParameter(_self).getTransform() - return _BJS_Closure_20BridgeJSRuntimeTestsSS_SS.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -8025,10 +8637,10 @@ public func _bjs_TextProcessor_processOptionalGreeter(_ _self: UnsafeMutableRawP @_expose(wasm, "bjs_TextProcessor_makeOptionalStringFormatter") @_cdecl("bjs_TextProcessor_makeOptionalStringFormatter") -public func _bjs_TextProcessor_makeOptionalStringFormatter(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +public func _bjs_TextProcessor_makeOptionalStringFormatter(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) let ret = TextProcessor.bridgeJSLiftParameter(_self).makeOptionalStringFormatter() - return _BJS_Closure_20BridgeJSRuntimeTestsSqSS_SS.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -8036,10 +8648,10 @@ public func _bjs_TextProcessor_makeOptionalStringFormatter(_ _self: UnsafeMutabl @_expose(wasm, "bjs_TextProcessor_makeOptionalGreeterCreator") @_cdecl("bjs_TextProcessor_makeOptionalGreeterCreator") -public func _bjs_TextProcessor_makeOptionalGreeterCreator(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +public func _bjs_TextProcessor_makeOptionalGreeterCreator(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) let ret = TextProcessor.bridgeJSLiftParameter(_self).makeOptionalGreeterCreator() - return _BJS_Closure_20BridgeJSRuntimeTestsy_Sq7GreeterC.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -8091,10 +8703,10 @@ public func _bjs_TextProcessor_processAPIResult(_ _self: UnsafeMutableRawPointer @_expose(wasm, "bjs_TextProcessor_makeDirectionChecker") @_cdecl("bjs_TextProcessor_makeDirectionChecker") -public func _bjs_TextProcessor_makeDirectionChecker(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +public func _bjs_TextProcessor_makeDirectionChecker(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) let ret = TextProcessor.bridgeJSLiftParameter(_self).makeDirectionChecker() - return _BJS_Closure_20BridgeJSRuntimeTests9DirectionO_Sb.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -8102,10 +8714,10 @@ public func _bjs_TextProcessor_makeDirectionChecker(_ _self: UnsafeMutableRawPoi @_expose(wasm, "bjs_TextProcessor_makeThemeValidator") @_cdecl("bjs_TextProcessor_makeThemeValidator") -public func _bjs_TextProcessor_makeThemeValidator(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +public func _bjs_TextProcessor_makeThemeValidator(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) let ret = TextProcessor.bridgeJSLiftParameter(_self).makeThemeValidator() - return _BJS_Closure_20BridgeJSRuntimeTests5ThemeO_Sb.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -8113,10 +8725,10 @@ public func _bjs_TextProcessor_makeThemeValidator(_ _self: UnsafeMutableRawPoint @_expose(wasm, "bjs_TextProcessor_makeStatusCodeExtractor") @_cdecl("bjs_TextProcessor_makeStatusCodeExtractor") -public func _bjs_TextProcessor_makeStatusCodeExtractor(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +public func _bjs_TextProcessor_makeStatusCodeExtractor(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) let ret = TextProcessor.bridgeJSLiftParameter(_self).makeStatusCodeExtractor() - return _BJS_Closure_20BridgeJSRuntimeTests10HttpStatusO_Si.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -8124,10 +8736,10 @@ public func _bjs_TextProcessor_makeStatusCodeExtractor(_ _self: UnsafeMutableRaw @_expose(wasm, "bjs_TextProcessor_makeAPIResultHandler") @_cdecl("bjs_TextProcessor_makeAPIResultHandler") -public func _bjs_TextProcessor_makeAPIResultHandler(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +public func _bjs_TextProcessor_makeAPIResultHandler(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) let ret = TextProcessor.bridgeJSLiftParameter(_self).makeAPIResultHandler() - return _BJS_Closure_20BridgeJSRuntimeTests9APIResultO_SS.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -8168,10 +8780,10 @@ public func _bjs_TextProcessor_processOptionalAPIResult(_ _self: UnsafeMutableRa @_expose(wasm, "bjs_TextProcessor_makeOptionalDirectionFormatter") @_cdecl("bjs_TextProcessor_makeOptionalDirectionFormatter") -public func _bjs_TextProcessor_makeOptionalDirectionFormatter(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +public func _bjs_TextProcessor_makeOptionalDirectionFormatter(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) let ret = TextProcessor.bridgeJSLiftParameter(_self).makeOptionalDirectionFormatter() - return _BJS_Closure_20BridgeJSRuntimeTestsSq9DirectionO_SS.bridgeJSLower(ret) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -8302,162 +8914,484 @@ public func _bjs_OptionalPropertyHolder_optionalName_get(_ _self: UnsafeMutableR #endif } -@_expose(wasm, "bjs_OptionalPropertyHolder_optionalName_set") -@_cdecl("bjs_OptionalPropertyHolder_optionalName_set") -public func _bjs_OptionalPropertyHolder_optionalName_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { - #if arch(wasm32) - OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalName = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) - #else - fatalError("Only available on WebAssembly") - #endif +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalName_set") +@_cdecl("bjs_OptionalPropertyHolder_optionalName_set") +public func _bjs_OptionalPropertyHolder_optionalName_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalName = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalAge_get") +@_cdecl("bjs_OptionalPropertyHolder_optionalAge_get") +public func _bjs_OptionalPropertyHolder_optionalAge_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalAge + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalAge_set") +@_cdecl("bjs_OptionalPropertyHolder_optionalAge_set") +public func _bjs_OptionalPropertyHolder_optionalAge_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalAge = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalGreeter_get") +@_cdecl("bjs_OptionalPropertyHolder_optionalGreeter_get") +public func _bjs_OptionalPropertyHolder_optionalGreeter_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalGreeter + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalGreeter_set") +@_cdecl("bjs_OptionalPropertyHolder_optionalGreeter_set") +public func _bjs_OptionalPropertyHolder_optionalGreeter_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalGreeter = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_deinit") +@_cdecl("bjs_OptionalPropertyHolder_deinit") +public func _bjs_OptionalPropertyHolder_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension OptionalPropertyHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_OptionalPropertyHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalPropertyHolder_wrap") +fileprivate func _bjs_OptionalPropertyHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_OptionalPropertyHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_Container_init") +@_cdecl("bjs_Container_init") +public func _bjs_Container_init(_ config: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let _tmp_config = Optional.bridgeJSLiftParameter(config) + let _tmp_location = DataPoint.bridgeJSLiftParameter() + let ret = Container(location: _tmp_location, config: _tmp_config) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_location_get") +@_cdecl("bjs_Container_location_get") +public func _bjs_Container_location_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Container.bridgeJSLiftParameter(_self).location + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_location_set") +@_cdecl("bjs_Container_location_set") +public func _bjs_Container_location_set(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Container.bridgeJSLiftParameter(_self).location = DataPoint.bridgeJSLiftParameter() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_config_get") +@_cdecl("bjs_Container_config_get") +public func _bjs_Container_config_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Container.bridgeJSLiftParameter(_self).config + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_config_set") +@_cdecl("bjs_Container_config_set") +public func _bjs_Container_config_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + Container.bridgeJSLiftParameter(_self).config = Optional.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_deinit") +@_cdecl("bjs_Container_deinit") +public func _bjs_Container_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Container: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Container_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Container_wrap") +fileprivate func _bjs_Container_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Container_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsApplyVoid_static") +fileprivate func bjs_ClosureSupportImports_jsApplyVoid_static(_ callback: Int32) -> Void +#else +fileprivate func bjs_ClosureSupportImports_jsApplyVoid_static(_ callback: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsApplyBool_static") +fileprivate func bjs_ClosureSupportImports_jsApplyBool_static(_ callback: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsApplyBool_static(_ callback: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsApplyInt_static") +fileprivate func bjs_ClosureSupportImports_jsApplyInt_static(_ value: Int32, _ transform: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsApplyInt_static(_ value: Int32, _ transform: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsApplyDouble_static") +fileprivate func bjs_ClosureSupportImports_jsApplyDouble_static(_ value: Float64, _ transform: Int32) -> Float64 +#else +fileprivate func bjs_ClosureSupportImports_jsApplyDouble_static(_ value: Float64, _ transform: Int32) -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsApplyString_static") +fileprivate func bjs_ClosureSupportImports_jsApplyString_static(_ value: Int32, _ transform: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsApplyString_static(_ value: Int32, _ transform: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsApplyJSObject_static") +fileprivate func bjs_ClosureSupportImports_jsApplyJSObject_static(_ value: Int32, _ transform: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsApplyJSObject_static(_ value: Int32, _ transform: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsMakeIntToInt_static") +fileprivate func bjs_ClosureSupportImports_jsMakeIntToInt_static(_ base: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsMakeIntToInt_static(_ base: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsMakeDoubleToDouble_static") +fileprivate func bjs_ClosureSupportImports_jsMakeDoubleToDouble_static(_ base: Float64) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsMakeDoubleToDouble_static(_ base: Float64) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsMakeStringToString_static") +fileprivate func bjs_ClosureSupportImports_jsMakeStringToString_static(_ prefix: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsMakeStringToString_static(_ prefix: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsCallTwice_static") +fileprivate func bjs_ClosureSupportImports_jsCallTwice_static(_ value: Int32, _ callback: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsCallTwice_static(_ value: Int32, _ callback: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsCallBinary_static") +fileprivate func bjs_ClosureSupportImports_jsCallBinary_static(_ callback: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsCallBinary_static(_ callback: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsCallTriple_static") +fileprivate func bjs_ClosureSupportImports_jsCallTriple_static(_ callback: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsCallTriple_static(_ callback: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsCallAfterRelease_static") +fileprivate func bjs_ClosureSupportImports_jsCallAfterRelease_static(_ callback: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsCallAfterRelease_static(_ callback: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsOptionalInvoke_static") +fileprivate func bjs_ClosureSupportImports_jsOptionalInvoke_static(_ callbackIsSome: Int32, _ callbackFuncRef: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsOptionalInvoke_static(_ callbackIsSome: Int32, _ callbackFuncRef: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsStoreClosure_static") +fileprivate func bjs_ClosureSupportImports_jsStoreClosure_static(_ callback: Int32) -> Void +#else +fileprivate func bjs_ClosureSupportImports_jsStoreClosure_static(_ callback: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsCallStoredClosure_static") +fileprivate func bjs_ClosureSupportImports_jsCallStoredClosure_static() -> Void +#else +fileprivate func bjs_ClosureSupportImports_jsCallStoredClosure_static() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsHeapCount_static") +fileprivate func bjs_ClosureSupportImports_jsHeapCount_static() -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsHeapCount_static() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_runJsClosureSupportTests_static") +fileprivate func bjs_ClosureSupportImports_runJsClosureSupportTests_static() -> Void +#else +fileprivate func bjs_ClosureSupportImports_runJsClosureSupportTests_static() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$ClosureSupportImports_jsApplyVoid(_ callback: JSTypedClosure<() -> Void>) throws(JSException) -> Void { + let callbackFuncRef = callback.bridgeJSLowerParameter() + bjs_ClosureSupportImports_jsApplyVoid_static(callbackFuncRef) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$ClosureSupportImports_jsApplyBool(_ callback: JSTypedClosure<() -> Bool>) throws(JSException) -> Bool { + let callbackFuncRef = callback.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsApplyBool_static(callbackFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return Bool.bridgeJSLiftReturn(ret) +} + +func _$ClosureSupportImports_jsApplyInt(_ value: Int, _ transform: JSTypedClosure<(Int) -> Int>) throws(JSException) -> Int { + let valueValue = value.bridgeJSLowerParameter() + let transformFuncRef = transform.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsApplyInt_static(valueValue, transformFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return Int.bridgeJSLiftReturn(ret) } -@_expose(wasm, "bjs_OptionalPropertyHolder_optionalAge_get") -@_cdecl("bjs_OptionalPropertyHolder_optionalAge_get") -public func _bjs_OptionalPropertyHolder_optionalAge_get(_ _self: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - let ret = OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalAge - return ret.bridgeJSLowerReturn() - #else - fatalError("Only available on WebAssembly") - #endif +func _$ClosureSupportImports_jsApplyDouble(_ value: Double, _ transform: JSTypedClosure<(Double) -> Double>) throws(JSException) -> Double { + let valueValue = value.bridgeJSLowerParameter() + let transformFuncRef = transform.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsApplyDouble_static(valueValue, transformFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return Double.bridgeJSLiftReturn(ret) } -@_expose(wasm, "bjs_OptionalPropertyHolder_optionalAge_set") -@_cdecl("bjs_OptionalPropertyHolder_optionalAge_set") -public func _bjs_OptionalPropertyHolder_optionalAge_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { - #if arch(wasm32) - OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalAge = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) - #else - fatalError("Only available on WebAssembly") - #endif +func _$ClosureSupportImports_jsApplyString(_ value: String, _ transform: JSTypedClosure<(String) -> String>) throws(JSException) -> String { + let valueValue = value.bridgeJSLowerParameter() + let transformFuncRef = transform.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsApplyString_static(valueValue, transformFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) } -@_expose(wasm, "bjs_OptionalPropertyHolder_optionalGreeter_get") -@_cdecl("bjs_OptionalPropertyHolder_optionalGreeter_get") -public func _bjs_OptionalPropertyHolder_optionalGreeter_get(_ _self: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - let ret = OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalGreeter - return ret.bridgeJSLowerReturn() - #else - fatalError("Only available on WebAssembly") - #endif +func _$ClosureSupportImports_jsApplyJSObject(_ value: JSObject, _ transform: JSTypedClosure<(JSObject) -> JSObject>) throws(JSException) -> JSObject { + let valueValue = value.bridgeJSLowerParameter() + let transformFuncRef = transform.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsApplyJSObject_static(valueValue, transformFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) } -@_expose(wasm, "bjs_OptionalPropertyHolder_optionalGreeter_set") -@_cdecl("bjs_OptionalPropertyHolder_optionalGreeter_set") -public func _bjs_OptionalPropertyHolder_optionalGreeter_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalGreeter = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) - #else - fatalError("Only available on WebAssembly") - #endif +func _$ClosureSupportImports_jsMakeIntToInt(_ base: Int) throws(JSException) -> (Int) -> Int { + let baseValue = base.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsMakeIntToInt_static(baseValue) + if let error = _swift_js_take_exception() { + throw error + } + return _BJS_Closure_20BridgeJSRuntimeTestsSi_Si.bridgeJSLift(ret) } -@_expose(wasm, "bjs_OptionalPropertyHolder_deinit") -@_cdecl("bjs_OptionalPropertyHolder_deinit") -public func _bjs_OptionalPropertyHolder_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - Unmanaged.fromOpaque(pointer).release() - #else - fatalError("Only available on WebAssembly") - #endif +func _$ClosureSupportImports_jsMakeDoubleToDouble(_ base: Double) throws(JSException) -> (Double) -> Double { + let baseValue = base.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsMakeDoubleToDouble_static(baseValue) + if let error = _swift_js_take_exception() { + throw error + } + return _BJS_Closure_20BridgeJSRuntimeTestsSd_Sd.bridgeJSLift(ret) } -extension OptionalPropertyHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { - var jsValue: JSValue { - return .object(JSObject(id: UInt32(bitPattern: _bjs_OptionalPropertyHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) +func _$ClosureSupportImports_jsMakeStringToString(_ prefix: String) throws(JSException) -> (String) -> String { + let prefixValue = prefix.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsMakeStringToString_static(prefixValue) + if let error = _swift_js_take_exception() { + throw error } + return _BJS_Closure_20BridgeJSRuntimeTestsSS_SS.bridgeJSLift(ret) } -#if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalPropertyHolder_wrap") -fileprivate func _bjs_OptionalPropertyHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 -#else -fileprivate func _bjs_OptionalPropertyHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { - fatalError("Only available on WebAssembly") +func _$ClosureSupportImports_jsCallTwice(_ value: Int, _ callback: JSTypedClosure<(Int) -> Void>) throws(JSException) -> Int { + let valueValue = value.bridgeJSLowerParameter() + let callbackFuncRef = callback.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsCallTwice_static(valueValue, callbackFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return Int.bridgeJSLiftReturn(ret) } -#endif -@_expose(wasm, "bjs_Container_init") -@_cdecl("bjs_Container_init") -public func _bjs_Container_init(_ config: Int32) -> UnsafeMutableRawPointer { - #if arch(wasm32) - let _tmp_config = Optional.bridgeJSLiftParameter(config) - let _tmp_location = DataPoint.bridgeJSLiftParameter() - let ret = Container(location: _tmp_location, config: _tmp_config) - return ret.bridgeJSLowerReturn() - #else - fatalError("Only available on WebAssembly") - #endif +func _$ClosureSupportImports_jsCallBinary(_ callback: JSTypedClosure<(Int, Int) -> Int>) throws(JSException) -> Int { + let callbackFuncRef = callback.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsCallBinary_static(callbackFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return Int.bridgeJSLiftReturn(ret) } -@_expose(wasm, "bjs_Container_location_get") -@_cdecl("bjs_Container_location_get") -public func _bjs_Container_location_get(_ _self: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - let ret = Container.bridgeJSLiftParameter(_self).location - return ret.bridgeJSLowerReturn() - #else - fatalError("Only available on WebAssembly") - #endif +func _$ClosureSupportImports_jsCallTriple(_ callback: JSTypedClosure<(Int, Int, Int) -> Int>) throws(JSException) -> Int { + let callbackFuncRef = callback.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsCallTriple_static(callbackFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return Int.bridgeJSLiftReturn(ret) } -@_expose(wasm, "bjs_Container_location_set") -@_cdecl("bjs_Container_location_set") -public func _bjs_Container_location_set(_ _self: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - Container.bridgeJSLiftParameter(_self).location = DataPoint.bridgeJSLiftParameter() - #else - fatalError("Only available on WebAssembly") - #endif +func _$ClosureSupportImports_jsCallAfterRelease(_ callback: JSTypedClosure<() -> Void>) throws(JSException) -> String { + let callbackFuncRef = callback.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsCallAfterRelease_static(callbackFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) } -@_expose(wasm, "bjs_Container_config_get") -@_cdecl("bjs_Container_config_get") -public func _bjs_Container_config_get(_ _self: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - let ret = Container.bridgeJSLiftParameter(_self).config - return ret.bridgeJSLowerReturn() - #else - fatalError("Only available on WebAssembly") - #endif +func _$ClosureSupportImports_jsOptionalInvoke(_ callback: Optional Bool>>) throws(JSException) -> Bool { + let (callbackIsSome, callbackFuncRef) = callback.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsOptionalInvoke_static(callbackIsSome, callbackFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return Bool.bridgeJSLiftReturn(ret) } -@_expose(wasm, "bjs_Container_config_set") -@_cdecl("bjs_Container_config_set") -public func _bjs_Container_config_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { - #if arch(wasm32) - Container.bridgeJSLiftParameter(_self).config = Optional.bridgeJSLiftParameter(value) - #else - fatalError("Only available on WebAssembly") - #endif +func _$ClosureSupportImports_jsStoreClosure(_ callback: JSTypedClosure<() -> Void>) throws(JSException) -> Void { + let callbackFuncRef = callback.bridgeJSLowerParameter() + bjs_ClosureSupportImports_jsStoreClosure_static(callbackFuncRef) + if let error = _swift_js_take_exception() { + throw error + } } -@_expose(wasm, "bjs_Container_deinit") -@_cdecl("bjs_Container_deinit") -public func _bjs_Container_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - Unmanaged.fromOpaque(pointer).release() - #else - fatalError("Only available on WebAssembly") - #endif +func _$ClosureSupportImports_jsCallStoredClosure() throws(JSException) -> Void { + bjs_ClosureSupportImports_jsCallStoredClosure_static() + if let error = _swift_js_take_exception() { + throw error + } } -extension Container: ConvertibleToJSValue, _BridgedSwiftHeapObject { - var jsValue: JSValue { - return .object(JSObject(id: UInt32(bitPattern: _bjs_Container_wrap(Unmanaged.passRetained(self).toOpaque())))) +func _$ClosureSupportImports_jsHeapCount() throws(JSException) -> Int { + let ret = bjs_ClosureSupportImports_jsHeapCount_static() + if let error = _swift_js_take_exception() { + throw error } + return Int.bridgeJSLiftReturn(ret) } -#if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Container_wrap") -fileprivate func _bjs_Container_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 -#else -fileprivate func _bjs_Container_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { - fatalError("Only available on WebAssembly") +func _$ClosureSupportImports_runJsClosureSupportTests() throws(JSException) -> Void { + bjs_ClosureSupportImports_runJsClosureSupportTests_static() + if let error = _swift_js_take_exception() { + throw error + } } -#endif #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripDictionary") @@ -9626,99 +10560,6 @@ func _$ArrayHost_firstLabel(_ self: JSObject, _ values: [String]) throws(JSExcep return String.bridgeJSLiftReturn(ret) } -#if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsApplyInt") -fileprivate func bjs_jsApplyInt(_ value: Int32, _ transform: UnsafeMutableRawPointer) -> Int32 -#else -fileprivate func bjs_jsApplyInt(_ value: Int32, _ transform: UnsafeMutableRawPointer) -> Int32 { - fatalError("Only available on WebAssembly") -} -#endif - -func _$jsApplyInt(_ value: Int, _ transform: @escaping (Int) -> Int) throws(JSException) -> Int { - let valueValue = value.bridgeJSLowerParameter() - let transformPointer = _BJS_Closure_20BridgeJSRuntimeTestsSi_Si.bridgeJSLower(transform) - let ret = bjs_jsApplyInt(valueValue, transformPointer) - if let error = _swift_js_take_exception() { - throw error - } - return Int.bridgeJSLiftReturn(ret) -} - -#if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsMakeAdder") -fileprivate func bjs_jsMakeAdder(_ base: Int32) -> Int32 -#else -fileprivate func bjs_jsMakeAdder(_ base: Int32) -> Int32 { - fatalError("Only available on WebAssembly") -} -#endif - -func _$jsMakeAdder(_ base: Int) throws(JSException) -> (Int) -> Int { - let baseValue = base.bridgeJSLowerParameter() - let ret = bjs_jsMakeAdder(baseValue) - if let error = _swift_js_take_exception() { - throw error - } - return _BJS_Closure_20BridgeJSRuntimeTestsSi_Si.bridgeJSLift(ret) -} - -#if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsMapString") -fileprivate func bjs_jsMapString(_ value: Int32, _ transform: UnsafeMutableRawPointer) -> Int32 -#else -fileprivate func bjs_jsMapString(_ value: Int32, _ transform: UnsafeMutableRawPointer) -> Int32 { - fatalError("Only available on WebAssembly") -} -#endif - -func _$jsMapString(_ value: String, _ transform: @escaping (String) -> String) throws(JSException) -> String { - let valueValue = value.bridgeJSLowerParameter() - let transformPointer = _BJS_Closure_20BridgeJSRuntimeTestsSS_SS.bridgeJSLower(transform) - let ret = bjs_jsMapString(valueValue, transformPointer) - if let error = _swift_js_take_exception() { - throw error - } - return String.bridgeJSLiftReturn(ret) -} - -#if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsMakePrefixer") -fileprivate func bjs_jsMakePrefixer(_ prefix: Int32) -> Int32 -#else -fileprivate func bjs_jsMakePrefixer(_ prefix: Int32) -> Int32 { - fatalError("Only available on WebAssembly") -} -#endif - -func _$jsMakePrefixer(_ prefix: String) throws(JSException) -> (String) -> String { - let prefixValue = prefix.bridgeJSLowerParameter() - let ret = bjs_jsMakePrefixer(prefixValue) - if let error = _swift_js_take_exception() { - throw error - } - return _BJS_Closure_20BridgeJSRuntimeTestsSS_SS.bridgeJSLift(ret) -} - -#if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsCallTwice") -fileprivate func bjs_jsCallTwice(_ value: Int32, _ callback: UnsafeMutableRawPointer) -> Int32 -#else -fileprivate func bjs_jsCallTwice(_ value: Int32, _ callback: UnsafeMutableRawPointer) -> Int32 { - fatalError("Only available on WebAssembly") -} -#endif - -func _$jsCallTwice(_ value: Int, _ callback: @escaping (Int) -> Void) throws(JSException) -> Int { - let valueValue = value.bridgeJSLowerParameter() - let callbackPointer = _BJS_Closure_20BridgeJSRuntimeTestsSi_y.bridgeJSLower(callback) - let ret = bjs_jsCallTwice(valueValue, callbackPointer) - if let error = _swift_js_take_exception() { - throw error - } - return Int.bridgeJSLiftReturn(ret) -} - #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsTranslatePoint") fileprivate func bjs_jsTranslatePoint(_ point: Int32, _ dx: Int32, _ dy: Int32) -> Int32 diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json index 8171fd95..23f47b03 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json @@ -2,134 +2,165 @@ "exported" : { "classes" : [ { - "constructor" : { - "abiName" : "bjs_Greeter_init", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "parameters" : [ - { - "label" : "name", - "name" : "name", - "type" : { - "string" : { - - } - } - } - ] - }, - "explicitAccessControl" : "public", "methods" : [ { - "abiName" : "bjs_Greeter_greet", + "abiName" : "bjs_ClosureSupportExports_static_makeIntToInt", "effects" : { "isAsync" : false, - "isStatic" : false, + "isStatic" : true, "isThrows" : false }, - "name" : "greet", + "name" : "makeIntToInt", "parameters" : [ + { + "label" : "_", + "name" : "base", + "type" : { + "int" : { + } + } + } ], "returnType" : { - "string" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSi_Si", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "int" : { + + } + } + ], + "returnType" : { + "int" : { + } + } + }, + "useJSTypedClosure" : false + } + }, + "staticContext" : { + "className" : { + "_0" : "ClosureSupportExports" } } }, { - "abiName" : "bjs_Greeter_changeName", + "abiName" : "bjs_ClosureSupportExports_static_makeDoubleToDouble", "effects" : { "isAsync" : false, - "isStatic" : false, + "isStatic" : true, "isThrows" : false }, - "name" : "changeName", + "name" : "makeDoubleToDouble", "parameters" : [ { - "label" : "name", - "name" : "name", + "label" : "_", + "name" : "base", "type" : { - "string" : { + "double" : { } } } ], "returnType" : { - "void" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSd_Sd", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "double" : { + + } + } + ], + "returnType" : { + "double" : { + } + } + }, + "useJSTypedClosure" : false + } + }, + "staticContext" : { + "className" : { + "_0" : "ClosureSupportExports" } } }, { - "abiName" : "bjs_Greeter_greetWith", + "abiName" : "bjs_ClosureSupportExports_static_makeStringToString", "effects" : { "isAsync" : false, - "isStatic" : false, + "isStatic" : true, "isThrows" : false }, - "name" : "greetWith", + "name" : "makeStringToString", "parameters" : [ { - "label" : "greeter", - "name" : "greeter", - "type" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } - } - }, - { - "label" : "customGreeting", - "name" : "customGreeting", + "label" : "_", + "name" : "prefix", "type" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "20BridgeJSRuntimeTests7GreeterC_SS", - "moduleName" : "BridgeJSRuntimeTests", - "parameters" : [ - { - "swiftHeapObject" : { - "_0" : "Greeter" - } - } - ], - "returnType" : { - "string" : { + "string" : { - } - } - } } } } ], "returnType" : { - "string" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSS_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + } + } + }, + "useJSTypedClosure" : false + } + }, + "staticContext" : { + "className" : { + "_0" : "ClosureSupportExports" } } }, { - "abiName" : "bjs_Greeter_makeFormatter", + "abiName" : "bjs_ClosureSupportExports_static_makeJSIntToInt", "effects" : { "isAsync" : false, - "isStatic" : false, + "isStatic" : true, "isThrows" : false }, - "name" : "makeFormatter", + "name" : "makeJSIntToInt", "parameters" : [ { - "label" : "suffix", - "name" : "suffix", + "label" : "_", + "name" : "base", "type" : { - "string" : { + "int" : { } } @@ -140,38 +171,44 @@ "_0" : { "isAsync" : false, "isThrows" : false, - "mangleName" : "20BridgeJSRuntimeTestsSS_SS", + "mangleName" : "20BridgeJSRuntimeTestsSi_Si", "moduleName" : "BridgeJSRuntimeTests", "parameters" : [ { - "string" : { + "int" : { } } ], "returnType" : { - "string" : { + "int" : { } } - } + }, + "useJSTypedClosure" : true + } + }, + "staticContext" : { + "className" : { + "_0" : "ClosureSupportExports" } } }, { - "abiName" : "bjs_Greeter_static_makeCreator", + "abiName" : "bjs_ClosureSupportExports_static_makeJSDoubleToDouble", "effects" : { "isAsync" : false, "isStatic" : true, "isThrows" : false }, - "name" : "makeCreator", + "name" : "makeJSDoubleToDouble", "parameters" : [ { - "label" : "defaultName", - "name" : "defaultName", + "label" : "_", + "name" : "base", "type" : { - "string" : { + "double" : { } } @@ -182,51 +219,60 @@ "_0" : { "isAsync" : false, "isThrows" : false, - "mangleName" : "20BridgeJSRuntimeTestsSS_7GreeterC", + "mangleName" : "20BridgeJSRuntimeTestsSd_Sd", "moduleName" : "BridgeJSRuntimeTests", "parameters" : [ { - "string" : { + "double" : { } } ], "returnType" : { - "swiftHeapObject" : { - "_0" : "Greeter" + "double" : { + } } - } + }, + "useJSTypedClosure" : true } }, "staticContext" : { "className" : { - "_0" : "Greeter" + "_0" : "ClosureSupportExports" } } }, { - "abiName" : "bjs_Greeter_makeCustomGreeter", + "abiName" : "bjs_ClosureSupportExports_static_makeJSStringToString", "effects" : { "isAsync" : false, - "isStatic" : false, + "isStatic" : true, "isThrows" : false }, - "name" : "makeCustomGreeter", + "name" : "makeJSStringToString", "parameters" : [ + { + "label" : "_", + "name" : "prefix", + "type" : { + "string" : { + } + } + } ], "returnType" : { "closure" : { "_0" : { "isAsync" : false, "isThrows" : false, - "mangleName" : "20BridgeJSRuntimeTests7GreeterC_SS", + "mangleName" : "20BridgeJSRuntimeTestsSS_SS", "moduleName" : "BridgeJSRuntimeTests", "parameters" : [ { - "swiftHeapObject" : { - "_0" : "Greeter" + "string" : { + } } ], @@ -235,50 +281,305 @@ } } - } + }, + "useJSTypedClosure" : true + } + }, + "staticContext" : { + "className" : { + "_0" : "ClosureSupportExports" } } } ], - "name" : "Greeter", + "name" : "ClosureSupportExports", "properties" : [ - { - "isReadonly" : false, - "isStatic" : false, - "name" : "name", - "type" : { - "string" : { - } - } - }, - { - "isReadonly" : true, + ], + "swiftCallName" : "ClosureSupportExports" + }, + { + "constructor" : { + "abiName" : "bjs_Greeter_init", + "effects" : { + "isAsync" : false, "isStatic" : false, - "name" : "prefix", - "type" : { - "string" : { + "isThrows" : false + }, + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + } } } - } - ], - "swiftCallName" : "Greeter" - }, - { + ] + }, + "explicitAccessControl" : "public", "methods" : [ { - "abiName" : "bjs_Calculator_square", + "abiName" : "bjs_Greeter_greet", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "square", + "name" : "greet", "parameters" : [ - { - "label" : "value", - "name" : "value", + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_Greeter_changeName", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "changeName", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_Greeter_greetWith", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "greetWith", + "parameters" : [ + { + "label" : "greeter", + "name" : "greeter", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "label" : "customGreeting", + "name" : "customGreeting", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTests7GreeterC_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_Greeter_makeFormatter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeFormatter", + "parameters" : [ + { + "label" : "suffix", + "name" : "suffix", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSS_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_Greeter_static_makeCreator", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "makeCreator", + "parameters" : [ + { + "label" : "defaultName", + "name" : "defaultName", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSS_7GreeterC", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + "useJSTypedClosure" : false + } + }, + "staticContext" : { + "className" : { + "_0" : "Greeter" + } + } + }, + { + "abiName" : "bjs_Greeter_makeCustomGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeCustomGreeter", + "parameters" : [ + + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTests7GreeterC_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "name" : "Greeter", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "prefix", + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "Greeter" + }, + { + "methods" : [ + { + "abiName" : "bjs_Calculator_square", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "square", + "parameters" : [ + { + "label" : "value", + "name" : "value", "type" : { "int" : { @@ -2246,7 +2547,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -2328,7 +2630,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -2369,7 +2672,8 @@ } } - } + }, + "useJSTypedClosure" : false } } }, @@ -2409,7 +2713,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -2456,7 +2761,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -2503,7 +2809,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -2549,7 +2856,8 @@ } } - } + }, + "useJSTypedClosure" : false } } }, @@ -2584,7 +2892,8 @@ "_1" : "null" } } - } + }, + "useJSTypedClosure" : false } } }, @@ -2619,7 +2928,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -2662,7 +2972,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -2705,7 +3016,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -2747,7 +3059,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -2788,7 +3101,8 @@ } } - } + }, + "useJSTypedClosure" : false } } }, @@ -2823,7 +3137,8 @@ } } - } + }, + "useJSTypedClosure" : false } } }, @@ -2858,7 +3173,8 @@ } } - } + }, + "useJSTypedClosure" : false } } }, @@ -2892,7 +3208,8 @@ } } - } + }, + "useJSTypedClosure" : false } } }, @@ -2932,7 +3249,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -2980,7 +3298,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -3027,7 +3346,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -3073,7 +3393,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -8141,7 +8462,8 @@ } } - } + }, + "useJSTypedClosure" : false } } } @@ -8190,7 +8512,8 @@ } } - } + }, + "useJSTypedClosure" : false } } }, @@ -8232,7 +8555,8 @@ } } - } + }, + "useJSTypedClosure" : false } } }, @@ -10539,7 +10863,8 @@ "_1" : "null" } } - } + }, + "useJSTypedClosure" : false } } } @@ -12866,54 +13191,688 @@ "string" : { } - }, - "_1" : "null" - } - } - } - ], - "name" : "ArrayMembers", - "properties" : [ - { - "isReadonly" : true, - "isStatic" : false, - "name" : "ints", - "type" : { - "array" : { - "_0" : { + }, + "_1" : "null" + } + } + } + ], + "name" : "ArrayMembers", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "ints", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "optStrings", + "type" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "ArrayMembers" + } + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + + ], + "types" : [ + { + "getters" : [ + + ], + "methods" : [ + + ], + "name" : "ClosureSupportImports", + "setters" : [ + + ], + "staticMethods" : [ + { + "name" : "jsApplyVoid", + "parameters" : [ + { + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsy_y", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "jsApplyBool", + "parameters" : [ + { + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsy_Sb", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + + ], + "returnType" : { + "bool" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "name" : "jsApplyInt", + "parameters" : [ + { + "name" : "value", + "type" : { + "int" : { + + } + } + }, + { + "name" : "transform", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSi_Si", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "int" : { + + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "name" : "jsApplyDouble", + "parameters" : [ + { + "name" : "value", + "type" : { + "double" : { + + } + } + }, + { + "name" : "transform", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSd_Sd", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "double" : { + + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + { + "name" : "jsApplyString", + "parameters" : [ + { + "name" : "value", + "type" : { + "string" : { + + } + } + }, + { + "name" : "transform", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSS_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "name" : "jsApplyJSObject", + "parameters" : [ + { + "name" : "value", + "type" : { + "jsObject" : { + + } + } + }, + { + "name" : "transform", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTests8JSObjectC_8JSObjectC", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "jsObject" : { + + } + } + ], + "returnType" : { + "jsObject" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "jsObject" : { + + } + } + }, + { + "name" : "jsMakeIntToInt", + "parameters" : [ + { + "name" : "base", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSi_Si", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "int" : { + + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "name" : "jsMakeDoubleToDouble", + "parameters" : [ + { + "name" : "base", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSd_Sd", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "double" : { + + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "name" : "jsMakeStringToString", + "parameters" : [ + { + "name" : "prefix", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSS_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "name" : "jsCallTwice", + "parameters" : [ + { + "name" : "value", + "type" : { + "int" : { + + } + } + }, + { + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSi_y", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "int" : { + + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "name" : "jsCallBinary", + "parameters" : [ + { + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSiSi_Si", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "int" : { + + } + }, + { + "int" : { + + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "name" : "jsCallTriple", + "parameters" : [ + { + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSiSiSi_Si", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "int" : { + + } + }, + { + "int" : { + + } + }, + { + "int" : { + + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "name" : "jsCallAfterRelease", + "parameters" : [ + { + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsy_y", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "name" : "jsOptionalInvoke", + "parameters" : [ + { + "name" : "callback", + "type" : { + "nullable" : { + "_0" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsy_Sb", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + + ], + "returnType" : { + "bool" : { + + } + } + }, + "useJSTypedClosure" : true + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "name" : "jsStoreClosure", + "parameters" : [ + { + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsy_y", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "jsCallStoredClosure", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "jsHeapCount", + "parameters" : [ + + ], + "returnType" : { "int" : { } } - } - } - }, - { - "isReadonly" : true, - "isStatic" : false, - "name" : "optStrings", - "type" : { - "nullable" : { - "_0" : { - "array" : { - "_0" : { - "string" : { + }, + { + "name" : "runJsClosureSupportTests", + "parameters" : [ + + ], + "returnType" : { + "void" : { - } - } } - }, - "_1" : "null" + } } - } + ] } - ], - "swiftCallName" : "ArrayMembers" - } - ] - }, - "imported" : { - "children" : [ + ] + }, { "functions" : [ { @@ -14181,212 +15140,6 @@ } ] }, - { - "functions" : [ - { - "name" : "jsApplyInt", - "parameters" : [ - { - "name" : "value", - "type" : { - "int" : { - - } - } - }, - { - "name" : "transform", - "type" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "20BridgeJSRuntimeTestsSi_Si", - "moduleName" : "BridgeJSRuntimeTests", - "parameters" : [ - { - "int" : { - - } - } - ], - "returnType" : { - "int" : { - - } - } - } - } - } - } - ], - "returnType" : { - "int" : { - - } - } - }, - { - "name" : "jsMakeAdder", - "parameters" : [ - { - "name" : "base", - "type" : { - "int" : { - - } - } - } - ], - "returnType" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "20BridgeJSRuntimeTestsSi_Si", - "moduleName" : "BridgeJSRuntimeTests", - "parameters" : [ - { - "int" : { - - } - } - ], - "returnType" : { - "int" : { - - } - } - } - } - } - }, - { - "name" : "jsMapString", - "parameters" : [ - { - "name" : "value", - "type" : { - "string" : { - - } - } - }, - { - "name" : "transform", - "type" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "20BridgeJSRuntimeTestsSS_SS", - "moduleName" : "BridgeJSRuntimeTests", - "parameters" : [ - { - "string" : { - - } - } - ], - "returnType" : { - "string" : { - - } - } - } - } - } - } - ], - "returnType" : { - "string" : { - - } - } - }, - { - "name" : "jsMakePrefixer", - "parameters" : [ - { - "name" : "prefix", - "type" : { - "string" : { - - } - } - } - ], - "returnType" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "20BridgeJSRuntimeTestsSS_SS", - "moduleName" : "BridgeJSRuntimeTests", - "parameters" : [ - { - "string" : { - - } - } - ], - "returnType" : { - "string" : { - - } - } - } - } - } - }, - { - "name" : "jsCallTwice", - "parameters" : [ - { - "name" : "value", - "type" : { - "int" : { - - } - } - }, - { - "name" : "callback", - "type" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "20BridgeJSRuntimeTestsSi_y", - "moduleName" : "BridgeJSRuntimeTests", - "parameters" : [ - { - "int" : { - - } - } - ], - "returnType" : { - "void" : { - - } - } - } - } - } - } - ], - "returnType" : { - "int" : { - - } - } - } - ], - "types" : [ - - ] - }, { "functions" : [ { diff --git a/Tests/BridgeJSRuntimeTests/ImportAPITests.swift b/Tests/BridgeJSRuntimeTests/ImportAPITests.swift index 4aa96e1b..fa97c319 100644 --- a/Tests/BridgeJSRuntimeTests/ImportAPITests.swift +++ b/Tests/BridgeJSRuntimeTests/ImportAPITests.swift @@ -135,29 +135,6 @@ class ImportAPITests: XCTestCase { XCTAssertEqual(try greeter.prefix, "Hello") } - func testClosureParameterIntToInt() throws { - let result = try jsApplyInt(21) { $0 * 2 } - XCTAssertEqual(result, 42) - } - - func testClosureReturnIntToInt() throws { - let add10 = try jsMakeAdder(10) - XCTAssertEqual(add10(0), 10) - XCTAssertEqual(add10(32), 42) - } - - func testClosureParameterStringToString() throws { - let result = try jsMapString("Hello") { value in - value + ", world!" - } - XCTAssertEqual(result, "Hello, world!") - } - - func testClosureReturnStringToString() throws { - let prefixer = try jsMakePrefixer("Hello, ") - XCTAssertEqual(prefixer("world!"), "Hello, world!") - } - func testRoundTripIntArray() throws { let values = [1, 2, 3, 4, 5] let result = try jsRoundTripIntArray(values) @@ -185,13 +162,6 @@ class ImportAPITests: XCTestCase { XCTAssertEqual(try host.firstLabel(["zeta"]), "zeta") } - func testClosureParameterIntToVoid() throws { - var total = 0 - let ret = try jsCallTwice(5) { total += $0 } - XCTAssertEqual(ret, 5) - XCTAssertEqual(total, 10) - } - func testJSNameFunctionAndClass() throws { XCTAssertEqual(try _jsWeirdFunction(), 42) diff --git a/Tests/BridgeJSRuntimeTests/ImportClosureAPIs.swift b/Tests/BridgeJSRuntimeTests/ImportClosureAPIs.swift deleted file mode 100644 index bb913300..00000000 --- a/Tests/BridgeJSRuntimeTests/ImportClosureAPIs.swift +++ /dev/null @@ -1,11 +0,0 @@ -@_spi(Experimental) import JavaScriptKit - -@JSFunction func jsApplyInt(_ value: Int, _ transform: @escaping (Int) -> Int) throws(JSException) -> Int - -@JSFunction func jsMakeAdder(_ base: Int) throws(JSException) -> (Int) -> Int - -@JSFunction func jsMapString(_ value: String, _ transform: @escaping (String) -> String) throws(JSException) -> String - -@JSFunction func jsMakePrefixer(_ `prefix`: String) throws(JSException) -> (String) -> String - -@JSFunction func jsCallTwice(_ value: Int, _ callback: @escaping (Int) -> Void) throws(JSException) -> Int diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/ClosureSupportTests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/ClosureSupportTests.mjs new file mode 100644 index 00000000..0d5560fa --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/JavaScript/ClosureSupportTests.mjs @@ -0,0 +1,311 @@ +/** + * @returns {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Imports["ClosureSupportImports"]} + */ +export function getImports(importsContext) { + return { + jsApplyVoid: (fn) => { + fn(); + }, + jsApplyBool: (fn) => { + return fn(); + }, + jsApplyInt: (v, fn) => { + return fn(v); + }, + jsApplyDouble: (v, fn) => { + return fn(v); + }, + jsApplyString: (v, fn) => { + return fn(v); + }, + jsApplyJSValue: (v, fn) => { + return fn(v); + }, + jsApplyJSObject: (v, fn) => { + return fn(v); + }, + jsApplyArrayInt: (v, fn) => { + return fn(v); + }, + jsApplyArrayDouble: (v, fn) => { + return fn(v); + }, + jsApplyArrayString: (v, fn) => { + return fn(v); + }, + jsApplyArrayJSValue: (v, fn) => { + return fn(v); + }, + jsApplyArrayJSObject: (v, fn) => { + return fn(v); + }, + jsMakeIntToInt: (base) => { + return (v) => base + v; + }, + jsMakeDoubleToDouble: (base) => { + return (v) => base + v; + }, + jsMakeStringToString: (prefix) => { + return (name) => `${prefix}${name}`; + }, + jsCallTwice: (v, fn) => { + fn(v); + fn(v); + return v; + }, + jsCallBinary: (fn) => fn(1, 2), + jsCallTriple: (fn) => fn(1, 2, 3), + jsCallTripleMut: (fn) => { + fn(1, 2, 3); + fn(4, 5, 6); + }, + jsCallTwiceMut: (fn) => { + fn(); + fn(); + }, + jsHeapCount: () => { + globalThis.gc?.(); + return globalThis.swift?.memory?._heapValueById?.size ?? -1; + }, + jsCallAfterRelease: (fn) => { + try { + fn(); + fn(); + return "null"; + } catch (e) { + return e?.message ?? "error"; + } + }, + jsOptionalInvoke: (fn) => { + if (fn == null) { return false; } + return fn(); + }, + jsStoreClosure: (fn) => { globalThis.__storedClosure = fn; }, + jsCallStoredClosure: () => { return globalThis.__storedClosure?.(); }, + + runJsClosureSupportTests: () => { + const exports = importsContext.getExports(); + if (!exports) { throw new Error("No exports!?"); } + runJsClosureSupportTests(exports); + }, + }; +} + +import assert from "node:assert"; + +/** @param {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */ +export function runJsClosureSupportTests(exports) { + const upperTransform = (text) => text.toUpperCase(); + const processor = new exports.TextProcessor(upperTransform); + + assert.equal(processor.process("hello"), "HELLO"); + + const multiParamTransform = (count, text, ratio) => { + return `${text.toUpperCase()}-${count}-${ratio.toFixed(2)}`; + }; + assert.equal(processor.processWithCustom("world", multiParamTransform), "WORLD-42-3.14"); + assert.equal(processor.process("test"), "TEST"); + + const greeterForClosure = new exports.Greeter("World"); + const greeterCaller = new exports.Greeter("Caller"); + const customGreeting = (greeter) => `Custom greeting for ${greeter.name}: ${greeter.greet()}`; + const greetResult = greeterCaller.greetWith(greeterForClosure, customGreeting); + assert.equal(greetResult, "Custom greeting for World: Hello, World!"); + greeterForClosure.release(); + greeterCaller.release(); + + assert.equal(exports.formatName("ada", (name) => name.toUpperCase()), "ADA"); + assert.equal(exports.formatName("grace", (name) => `Dr. ${name}`), "Dr. grace"); + + const addDr = exports.makeFormatter("Dr."); + assert.equal(addDr("Ada"), "Dr. Ada"); + assert.equal(addDr("Grace"), "Dr. Grace"); + + const addProf = exports.makeFormatter("Prof."); + assert.equal(addProf("Hopper"), "Prof. Hopper"); + + const add10 = exports.makeAdder(10); + assert.equal(add10(5), 15); + assert.equal(add10(32), 42); + + const add100 = exports.makeAdder(100); + assert.equal(add100(23), 123); + + const storedTransform = processor.getTransform(); + assert.equal(storedTransform("hello"), "HELLO"); + assert.equal(storedTransform("world"), "WORLD"); + + const greeterForFormatter = new exports.Greeter("Formatter"); + const greeterFormatter = greeterForFormatter.makeFormatter(" [suffix]"); + assert.equal(greeterFormatter("test"), "Hello, Formatter! - test - [suffix]"); + assert.equal(greeterFormatter("data"), "Hello, Formatter! - data - [suffix]"); + greeterForFormatter.release(); + + const greeterCreator = exports.Greeter.makeCreator("Default"); + const createdG1 = greeterCreator("Alice"); + assert.equal(createdG1.name, "Alice"); + assert.equal(createdG1.greet(), "Hello, Alice!"); + const createdG2 = greeterCreator(""); + assert.equal(createdG2.name, "Default"); + assert.equal(createdG2.greet(), "Hello, Default!"); + createdG1.release(); + createdG2.release(); + + const greeterHost = new exports.Greeter("Host"); + const greeterGreeter = greeterHost.makeCustomGreeter(); + const guest1 = new exports.Greeter("Guest1"); + const guest2 = new exports.Greeter("Guest2"); + assert.equal(greeterGreeter(guest1), "Host greets Guest1: Hello, Guest1!"); + assert.equal(greeterGreeter(guest2), "Host greets Guest2: Hello, Guest2!"); + greeterHost.release(); + guest1.release(); + guest2.release(); + + const greeterForMethod = new exports.Greeter("Method"); + const greeterParam = new exports.Greeter("Param"); + const methodResult = greeterForMethod.greetWith(greeterParam, (g) => { + return `Custom: ${g.name} says ${g.greet()}`; + }); + assert.equal(methodResult, "Custom: Param says Hello, Param!"); + greeterForMethod.release(); + greeterParam.release(); + + const optResult1 = processor.processOptionalString((value) => { + return value !== null ? `Got: ${value}` : `Got: null`; + }); + assert.equal(optResult1, "Got: test | Got: null"); + + const optResult2 = processor.processOptionalInt((value) => { + return value !== null ? `Number: ${value}` : `Number: null`; + }); + assert.equal(optResult2, "Number: 42 | Number: null"); + + const optResult3 = processor.processOptionalGreeter((greeter) => { + return greeter !== null ? `Greeter: ${greeter.name}` : `Greeter: null`; + }); + assert.equal(optResult3, "Greeter: Alice | Greeter: null"); + + const optFormatter = processor.makeOptionalStringFormatter(); + assert.equal(optFormatter("world"), "Got: world"); + assert.equal(optFormatter(null), "Got: nil"); + + const optCreator = processor.makeOptionalGreeterCreator(); + const opt1 = optCreator(); + assert.equal(opt1, null); + const opt2 = optCreator(); + assert.notEqual(opt2, null); + assert.equal(opt2.name, "Greeter2"); + assert.equal(opt2.greet(), "Hello, Greeter2!"); + opt2.release(); + const opt3 = optCreator(); + assert.equal(opt3, null); + const opt4 = optCreator(); + assert.notEqual(opt4, null); + assert.equal(opt4.name, "Greeter4"); + opt4.release(); + + const dirResult = processor.processDirection((dir) => { + switch (dir) { + case exports.Direction.North: return "Going North"; + case exports.Direction.South: return "Going South"; + case exports.Direction.East: return "Going East"; + case exports.Direction.West: return "Going West"; + default: return "Unknown"; + } + }); + assert.equal(dirResult, "Going North"); + + const themeResult = processor.processTheme((theme) => { + return theme === exports.Theme.Dark ? "Dark mode" : "Light mode"; + }); + assert.equal(themeResult, "Dark mode"); + + const statusResult = processor.processHttpStatus((status) => { + return status; + }); + assert.equal(statusResult, exports.HttpStatus.Ok); + + const apiResult = processor.processAPIResult((result) => { + if (result.tag === exports.APIResult.Tag.Success) { + return `API Success: ${result.param0}`; + } + return "API Other"; + }); + assert.equal(apiResult, "API Success: test"); + + const dirChecker = processor.makeDirectionChecker(); + assert.equal(dirChecker(exports.Direction.North), true); + assert.equal(dirChecker(exports.Direction.South), true); + assert.equal(dirChecker(exports.Direction.East), false); + assert.equal(dirChecker(exports.Direction.West), false); + + const themeValidator = processor.makeThemeValidator(); + assert.equal(themeValidator(exports.Theme.Dark), true); + assert.equal(themeValidator(exports.Theme.Light), false); + assert.equal(themeValidator(exports.Theme.Auto), false); + + const statusExtractor = processor.makeStatusCodeExtractor(); + assert.equal(statusExtractor(exports.HttpStatus.Ok), 200); + assert.equal(statusExtractor(exports.HttpStatus.NotFound), 404); + assert.equal(statusExtractor(exports.HttpStatus.ServerError), 500); + assert.equal(statusExtractor(exports.HttpStatus.Unknown), -1); + + const apiHandler = processor.makeAPIResultHandler(); + assert.equal(apiHandler({ tag: exports.APIResult.Tag.Success, param0: "done" }), "Success: done"); + assert.equal(apiHandler({ tag: exports.APIResult.Tag.Failure, param0: 500 }), "Failure: 500"); + assert.equal(apiHandler({ tag: exports.APIResult.Tag.Info }), "Info"); + assert.equal(apiHandler({ tag: exports.APIResult.Tag.Flag, param0: true }), "Flag: true"); + assert.equal(apiHandler({ tag: exports.APIResult.Tag.Rate, param0: 1.5 }), "Rate: 1.5"); + assert.equal(apiHandler({ tag: exports.APIResult.Tag.Precise, param0: 3.14159 }), "Precise: 3.14159"); + + const optDirResult = processor.processOptionalDirection((dir) => { + return dir !== null ? `Dir: ${dir}` : "Dir: null"; + }); + assert.equal(optDirResult, `Dir: ${exports.Direction.North} | Dir: null`); + + const optThemeResult = processor.processOptionalTheme((theme) => { + return theme !== null ? `Theme: ${theme}` : "Theme: null"; + }); + assert.equal(optThemeResult, `Theme: ${exports.Theme.Light} | Theme: null`); + + const optApiResult = processor.processOptionalAPIResult((result) => { + if (result === null) return "Result: null"; + if (result.tag === exports.APIResult.Tag.Success) { + return `Result: Success(${result.param0})`; + } + return "Result: other"; + }); + assert.equal(optApiResult, "Result: Success(ok) | Result: null"); + + const optDirFormatter = processor.makeOptionalDirectionFormatter(); + assert.equal(optDirFormatter(exports.Direction.North), "N"); + assert.equal(optDirFormatter(exports.Direction.South), "S"); + assert.equal(optDirFormatter(exports.Direction.East), "E"); + assert.equal(optDirFormatter(exports.Direction.West), "W"); + assert.equal(optDirFormatter(null), "nil"); + + processor.release(); + + + const intToInt = exports.ClosureSupportExports.makeIntToInt(10); + assert.equal(intToInt(0), 10); + assert.equal(intToInt(32), 42); + + const doubleToDouble = exports.ClosureSupportExports.makeDoubleToDouble(10.0); + assert.equal(doubleToDouble(0.0), 10.0); + assert.equal(doubleToDouble(32.0), 42.0); + + const stringToString = exports.ClosureSupportExports.makeStringToString("Hello, "); + assert.equal(stringToString("world!"), "Hello, world!"); + + const jsIntToInt = exports.ClosureSupportExports.makeJSIntToInt(10); + assert.equal(jsIntToInt(0), 10); + assert.equal(jsIntToInt(32), 42); + + const jsDoubleToDouble = exports.ClosureSupportExports.makeJSDoubleToDouble(10.0); + assert.equal(jsDoubleToDouble(0.0), 10.0); + assert.equal(jsDoubleToDouble(32.0), 42.0); + + const jsStringToString = exports.ClosureSupportExports.makeJSStringToString("Hello, "); + assert.equal(jsStringToString("world!"), "Hello, world!"); +} diff --git a/Tests/JavaScriptKitTests/JavaScriptKitTests.swift b/Tests/JavaScriptKitTests/JavaScriptKitTests.swift index b69334ce..280a17b6 100644 --- a/Tests/JavaScriptKitTests/JavaScriptKitTests.swift +++ b/Tests/JavaScriptKitTests/JavaScriptKitTests.swift @@ -523,5 +523,9 @@ class JavaScriptKitTests: XCTestCase { } } +#if arch(wasm32) @_extern(c, "llvm.wasm.memory.grow.i32") func growMemory(_ memory: Int32, _ pages: Int32) -> Int32 +#else +func growMemory(_ memory: Int32, _ pages: Int32) -> Int32 { return 0 } +#endif diff --git a/Tests/prelude.mjs b/Tests/prelude.mjs index 934c4f01..95573b34 100644 --- a/Tests/prelude.mjs +++ b/Tests/prelude.mjs @@ -5,6 +5,7 @@ import { } from '../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.js'; import { ImportedFoo } from './BridgeJSRuntimeTests/JavaScript/Types.mjs'; import { runJsOptionalSupportTests } from './BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs'; +import { getImports as getClosureSupportImports } from './BridgeJSRuntimeTests/JavaScript/ClosureSupportTests.mjs'; /** @type {import('../.build/plugins/PackageToJS/outputs/PackageTests/test.d.ts').SetupOptionsFn} */ export async function setupOptions(options, context) { @@ -185,23 +186,6 @@ export async function setupOptions(options, context) { BridgeJSRuntimeTests_runAsyncWorks(exports); return; }, - jsApplyInt: (v, fn) => { - return fn(v); - }, - jsMakeAdder: (base) => { - return (v) => base + v; - }, - jsMapString: (value, fn) => { - return fn(value); - }, - jsMakePrefixer: (prefix) => { - return (name) => `${prefix}${name}`; - }, - jsCallTwice: (v, fn) => { - fn(v); - fn(v); - return v; - }, jsTranslatePoint: (point, dx, dy) => { return { x: (point.x | 0) + (dx | 0), y: (point.y | 0) + (dy | 0) }; }, @@ -227,7 +211,8 @@ export async function setupOptions(options, context) { const exports = importsContext.getExports(); if (!exports) { throw new Error("No exports!?"); } runJsOptionalSupportTests(exports); - } + }, + ClosureSupportImports: getClosureSupportImports(importsContext), }; }, addToCoreImports(importObject, importsContext) { @@ -893,202 +878,8 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { cd5.release(); testProtocolSupport(exports); - testClosureSupport(exports); testArraySupport(exports); } -/** @param {import('./../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */ -function testClosureSupport(exports) { - const upperTransform = (text) => text.toUpperCase(); - const processor = new exports.TextProcessor(upperTransform); - - assert.equal(processor.process("hello"), "HELLO"); - - const multiParamTransform = (count, text, ratio) => { - return `${text.toUpperCase()}-${count}-${ratio.toFixed(2)}`; - }; - assert.equal(processor.processWithCustom("world", multiParamTransform), "WORLD-42-3.14"); - assert.equal(processor.process("test"), "TEST"); - - const greeterForClosure = new exports.Greeter("World"); - const greeterCaller = new exports.Greeter("Caller"); - const customGreeting = (greeter) => `Custom greeting for ${greeter.name}: ${greeter.greet()}`; - const greetResult = greeterCaller.greetWith(greeterForClosure, customGreeting); - assert.equal(greetResult, "Custom greeting for World: Hello, World!"); - greeterForClosure.release(); - greeterCaller.release(); - - assert.equal(exports.formatName("ada", (name) => name.toUpperCase()), "ADA"); - assert.equal(exports.formatName("grace", (name) => `Dr. ${name}`), "Dr. grace"); - - const addDr = exports.makeFormatter("Dr."); - assert.equal(addDr("Ada"), "Dr. Ada"); - assert.equal(addDr("Grace"), "Dr. Grace"); - - const addProf = exports.makeFormatter("Prof."); - assert.equal(addProf("Hopper"), "Prof. Hopper"); - - const add10 = exports.makeAdder(10); - assert.equal(add10(5), 15); - assert.equal(add10(32), 42); - - const add100 = exports.makeAdder(100); - assert.equal(add100(23), 123); - - const storedTransform = processor.getTransform(); - assert.equal(storedTransform("hello"), "HELLO"); - assert.equal(storedTransform("world"), "WORLD"); - - const greeterForFormatter = new exports.Greeter("Formatter"); - const greeterFormatter = greeterForFormatter.makeFormatter(" [suffix]"); - assert.equal(greeterFormatter("test"), "Hello, Formatter! - test - [suffix]"); - assert.equal(greeterFormatter("data"), "Hello, Formatter! - data - [suffix]"); - greeterForFormatter.release(); - - const greeterCreator = exports.Greeter.makeCreator("Default"); - const createdG1 = greeterCreator("Alice"); - assert.equal(createdG1.name, "Alice"); - assert.equal(createdG1.greet(), "Hello, Alice!"); - const createdG2 = greeterCreator(""); - assert.equal(createdG2.name, "Default"); - assert.equal(createdG2.greet(), "Hello, Default!"); - createdG1.release(); - createdG2.release(); - - const greeterHost = new exports.Greeter("Host"); - const greeterGreeter = greeterHost.makeCustomGreeter(); - const guest1 = new exports.Greeter("Guest1"); - const guest2 = new exports.Greeter("Guest2"); - assert.equal(greeterGreeter(guest1), "Host greets Guest1: Hello, Guest1!"); - assert.equal(greeterGreeter(guest2), "Host greets Guest2: Hello, Guest2!"); - greeterHost.release(); - guest1.release(); - guest2.release(); - - const greeterForMethod = new exports.Greeter("Method"); - const greeterParam = new exports.Greeter("Param"); - const methodResult = greeterForMethod.greetWith(greeterParam, (g) => { - return `Custom: ${g.name} says ${g.greet()}`; - }); - assert.equal(methodResult, "Custom: Param says Hello, Param!"); - greeterForMethod.release(); - greeterParam.release(); - - const optResult1 = processor.processOptionalString((value) => { - return value !== null ? `Got: ${value}` : `Got: null`; - }); - assert.equal(optResult1, "Got: test | Got: null"); - - const optResult2 = processor.processOptionalInt((value) => { - return value !== null ? `Number: ${value}` : `Number: null`; - }); - assert.equal(optResult2, "Number: 42 | Number: null"); - - const optResult3 = processor.processOptionalGreeter((greeter) => { - return greeter !== null ? `Greeter: ${greeter.name}` : `Greeter: null`; - }); - assert.equal(optResult3, "Greeter: Alice | Greeter: null"); - - const optFormatter = processor.makeOptionalStringFormatter(); - assert.equal(optFormatter("world"), "Got: world"); - assert.equal(optFormatter(null), "Got: nil"); - - const optCreator = processor.makeOptionalGreeterCreator(); - const opt1 = optCreator(); - assert.equal(opt1, null); - const opt2 = optCreator(); - assert.notEqual(opt2, null); - assert.equal(opt2.name, "Greeter2"); - assert.equal(opt2.greet(), "Hello, Greeter2!"); - opt2.release(); - const opt3 = optCreator(); - assert.equal(opt3, null); - const opt4 = optCreator(); - assert.notEqual(opt4, null); - assert.equal(opt4.name, "Greeter4"); - opt4.release(); - - const dirResult = processor.processDirection((dir) => { - switch (dir) { - case exports.Direction.North: return "Going North"; - case exports.Direction.South: return "Going South"; - case exports.Direction.East: return "Going East"; - case exports.Direction.West: return "Going West"; - default: return "Unknown"; - } - }); - assert.equal(dirResult, "Going North"); - - const themeResult = processor.processTheme((theme) => { - return theme === exports.Theme.Dark ? "Dark mode" : "Light mode"; - }); - assert.equal(themeResult, "Dark mode"); - - const statusResult = processor.processHttpStatus((status) => { - return status; - }); - assert.equal(statusResult, exports.HttpStatus.Ok); - - const apiResult = processor.processAPIResult((result) => { - if (result.tag === exports.APIResult.Tag.Success) { - return `API Success: ${result.param0}`; - } - return "API Other"; - }); - assert.equal(apiResult, "API Success: test"); - - const dirChecker = processor.makeDirectionChecker(); - assert.equal(dirChecker(exports.Direction.North), true); - assert.equal(dirChecker(exports.Direction.South), true); - assert.equal(dirChecker(exports.Direction.East), false); - assert.equal(dirChecker(exports.Direction.West), false); - - const themeValidator = processor.makeThemeValidator(); - assert.equal(themeValidator(exports.Theme.Dark), true); - assert.equal(themeValidator(exports.Theme.Light), false); - assert.equal(themeValidator(exports.Theme.Auto), false); - - const statusExtractor = processor.makeStatusCodeExtractor(); - assert.equal(statusExtractor(exports.HttpStatus.Ok), 200); - assert.equal(statusExtractor(exports.HttpStatus.NotFound), 404); - assert.equal(statusExtractor(exports.HttpStatus.ServerError), 500); - assert.equal(statusExtractor(exports.HttpStatus.Unknown), -1); - - const apiHandler = processor.makeAPIResultHandler(); - assert.equal(apiHandler({ tag: exports.APIResult.Tag.Success, param0: "done" }), "Success: done"); - assert.equal(apiHandler({ tag: exports.APIResult.Tag.Failure, param0: 500 }), "Failure: 500"); - assert.equal(apiHandler({ tag: exports.APIResult.Tag.Info }), "Info"); - assert.equal(apiHandler({ tag: exports.APIResult.Tag.Flag, param0: true }), "Flag: true"); - assert.equal(apiHandler({ tag: exports.APIResult.Tag.Rate, param0: 1.5 }), "Rate: 1.5"); - assert.equal(apiHandler({ tag: exports.APIResult.Tag.Precise, param0: 3.14159 }), "Precise: 3.14159"); - - const optDirResult = processor.processOptionalDirection((dir) => { - return dir !== null ? `Dir: ${dir}` : "Dir: null"; - }); - assert.equal(optDirResult, `Dir: ${exports.Direction.North} | Dir: null`); - - const optThemeResult = processor.processOptionalTheme((theme) => { - return theme !== null ? `Theme: ${theme}` : "Theme: null"; - }); - assert.equal(optThemeResult, `Theme: ${exports.Theme.Light} | Theme: null`); - - const optApiResult = processor.processOptionalAPIResult((result) => { - if (result === null) return "Result: null"; - if (result.tag === exports.APIResult.Tag.Success) { - return `Result: Success(${result.param0})`; - } - return "Result: other"; - }); - assert.equal(optApiResult, "Result: Success(ok) | Result: null"); - - const optDirFormatter = processor.makeOptionalDirectionFormatter(); - assert.equal(optDirFormatter(exports.Direction.North), "N"); - assert.equal(optDirFormatter(exports.Direction.South), "S"); - assert.equal(optDirFormatter(exports.Direction.East), "E"); - assert.equal(optDirFormatter(exports.Direction.West), "W"); - assert.equal(optDirFormatter(null), "nil"); - - processor.release(); -} /** @param {import('./../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */ function testStructSupport(exports) {