From 1656b22347ffc228c0a631b1c71e259750536698 Mon Sep 17 00:00:00 2001 From: Krzysztof Rodak Date: Tue, 17 Feb 2026 10:11:06 +0100 Subject: [PATCH] NFC: BridgeJS: Refactor to descriptor-driven codegen, remove dead cleanup infrastructure --- Benchmarks/Sources/Generated/BridgeJS.swift | 45 +- .../PlayBridgeJS/Generated/BridgeJS.swift | 27 +- .../Sources/BridgeJSCore/ClosureCodegen.swift | 12 +- .../Sources/BridgeJSCore/ExportSwift.swift | 407 +-- .../Sources/BridgeJSCore/ImportTS.swift | 179 +- .../Sources/BridgeJSLink/BridgeJSLink.swift | 78 +- .../Sources/BridgeJSLink/JSGlueGen.swift | 2538 ++++++----------- .../BridgeJSSkeleton/BridgeJSSkeleton.swift | 719 +++-- .../BridgeJSCodegenTests/ArrayTypes.swift | 9 +- ...CrossFileTypeResolution.ReverseOrder.swift | 4 +- .../CrossFileTypeResolution.swift | 4 +- .../DefaultParameters.swift | 18 +- .../EnumAssociatedValue.swift | 9 +- .../ImportedTypeInExportedInterface.swift | 9 +- .../BridgeJSCodegenTests/Optionals.swift | 12 +- .../BridgeJSCodegenTests/Protocol.swift | 2 +- .../BridgeJSCodegenTests/SwiftClosure.swift | 4 +- .../BridgeJSCodegenTests/SwiftStruct.swift | 63 +- .../SwiftStructImports.swift | 9 +- .../BridgeJSCodegenTests/UnsafePointer.swift | 9 +- .../BridgeJSLinkTests/ArrayTypes.js | 144 +- .../__Snapshots__/BridgeJSLinkTests/Async.js | 14 +- .../BridgeJSLinkTests/DefaultParameters.js | 202 +- .../BridgeJSLinkTests/DictionaryTypes.js | 31 +- .../BridgeJSLinkTests/EnumAssociatedValue.js | 1484 +++++----- .../BridgeJSLinkTests/EnumCase.js | 14 +- .../BridgeJSLinkTests/EnumNamespace.Global.js | 14 +- .../BridgeJSLinkTests/EnumNamespace.js | 14 +- .../BridgeJSLinkTests/EnumRawType.js | 60 +- .../BridgeJSLinkTests/GlobalGetter.js | 14 +- .../BridgeJSLinkTests/GlobalThisImports.js | 14 +- .../BridgeJSLinkTests/ImportArray.js | 15 +- .../ImportedTypeInExportedInterface.js | 115 +- .../BridgeJSLinkTests/InvalidPropertyNames.js | 14 +- .../BridgeJSLinkTests/JSClass.js | 14 +- .../JSClassStaticFunctions.js | 14 +- .../BridgeJSLinkTests/JSValue.js | 101 +- .../BridgeJSLinkTests/MixedGlobal.js | 14 +- .../BridgeJSLinkTests/MixedModules.js | 14 +- .../BridgeJSLinkTests/MixedPrivate.js | 14 +- .../BridgeJSLinkTests/Namespaces.Global.js | 14 +- .../BridgeJSLinkTests/Namespaces.js | 14 +- .../BridgeJSLinkTests/Optionals.js | 310 +- .../BridgeJSLinkTests/PrimitiveParameters.js | 14 +- .../BridgeJSLinkTests/PrimitiveReturn.js | 14 +- .../BridgeJSLinkTests/PropertyTypes.js | 14 +- .../BridgeJSLinkTests/Protocol.js | 145 +- .../StaticFunctions.Global.js | 83 +- .../BridgeJSLinkTests/StaticFunctions.js | 83 +- .../StaticProperties.Global.js | 28 +- .../BridgeJSLinkTests/StaticProperties.js | 28 +- .../BridgeJSLinkTests/StringParameter.js | 14 +- .../BridgeJSLinkTests/StringReturn.js | 14 +- .../BridgeJSLinkTests/SwiftClass.js | 18 +- .../BridgeJSLinkTests/SwiftClosure.js | 264 +- .../BridgeJSLinkTests/SwiftClosureImports.js | 14 +- .../BridgeJSLinkTests/SwiftStruct.js | 496 ++-- .../BridgeJSLinkTests/SwiftStructImports.js | 47 +- .../__Snapshots__/BridgeJSLinkTests/Throws.js | 14 +- .../BridgeJSLinkTests/UnsafePointer.js | 62 +- .../VoidParameterVoidReturn.js | 14 +- .../JavaScriptKit/BridgeJSIntrinsics.swift | 15 - .../Generated/BridgeJS.swift | 217 +- .../JavaScript/OptionalSupportTests.mjs | 409 ++- 64 files changed, 3748 insertions(+), 5074 deletions(-) diff --git a/Benchmarks/Sources/Generated/BridgeJS.swift b/Benchmarks/Sources/Generated/BridgeJS.swift index 6ec87dca8..65e57bdf9 100644 --- a/Benchmarks/Sources/Generated/BridgeJS.swift +++ b/Benchmarks/Sources/Generated/BridgeJS.swift @@ -132,10 +132,7 @@ extension SimpleStruct: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_SimpleStruct(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_SimpleStruct(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -148,9 +145,9 @@ extension SimpleStruct: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_SimpleStruct") -fileprivate func _bjs_struct_lower_SimpleStruct(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_SimpleStruct(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_SimpleStruct(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_SimpleStruct(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -179,10 +176,7 @@ extension Address: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_Address(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_Address(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -195,9 +189,9 @@ extension Address: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Address") -fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -232,10 +226,7 @@ extension Person: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_Person(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_Person(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -248,9 +239,9 @@ extension Person: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Person") -fileprivate func _bjs_struct_lower_Person(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_Person(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_Person(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_Person(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -285,10 +276,7 @@ extension ComplexStruct: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_ComplexStruct(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_ComplexStruct(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -301,9 +289,9 @@ extension ComplexStruct: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_ComplexStruct") -fileprivate func _bjs_struct_lower_ComplexStruct(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_ComplexStruct(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_ComplexStruct(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_ComplexStruct(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -330,10 +318,7 @@ extension Point: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -346,9 +331,9 @@ extension Point: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Point") -fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.swift b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.swift index 6e146dbc3..f2aaa9794 100644 --- a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.swift +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.swift @@ -24,10 +24,7 @@ extension PlayBridgeJSOutput: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_PlayBridgeJSOutput(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_PlayBridgeJSOutput(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -40,9 +37,9 @@ extension PlayBridgeJSOutput: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_PlayBridgeJSOutput") -fileprivate func _bjs_struct_lower_PlayBridgeJSOutput(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_PlayBridgeJSOutput(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_PlayBridgeJSOutput(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_PlayBridgeJSOutput(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -77,10 +74,7 @@ extension PlayBridgeJSDiagnostic: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_PlayBridgeJSDiagnostic(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_PlayBridgeJSDiagnostic(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -93,9 +87,9 @@ extension PlayBridgeJSDiagnostic: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_PlayBridgeJSDiagnostic") -fileprivate func _bjs_struct_lower_PlayBridgeJSDiagnostic(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_PlayBridgeJSDiagnostic(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_PlayBridgeJSDiagnostic(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_PlayBridgeJSDiagnostic(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -122,10 +116,7 @@ extension PlayBridgeJSResult: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_PlayBridgeJSResult(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_PlayBridgeJSResult(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -138,9 +129,9 @@ extension PlayBridgeJSResult: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_PlayBridgeJSResult") -fileprivate func _bjs_struct_lower_PlayBridgeJSResult(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_PlayBridgeJSResult(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_PlayBridgeJSResult(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_PlayBridgeJSResult(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift index cbec4ba31..01dd419e7 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift @@ -123,23 +123,23 @@ public struct ClosureCodegen { for (index, paramType) in signature.parameters.enumerated() { let paramName = "param\(index)" - let liftInfo = try paramType.liftParameterInfo() + let liftParams = try paramType.liftParameterInfo() - for (argName, wasmType) in liftInfo.parameters { + for (argName, wasmType) in liftParams { let fullName = - liftInfo.parameters.count > 1 ? "\(paramName)\(argName.capitalizedFirstLetter)" : paramName + liftParams.count > 1 ? "\(paramName)\(argName.capitalizedFirstLetter)" : paramName abiParams.append((fullName, wasmType)) } - let argNames = liftInfo.parameters.map { (argName, _) in - liftInfo.parameters.count > 1 ? "\(paramName)\(argName.capitalizedFirstLetter)" : paramName + let argNames = liftParams.map { (argName, _) in + liftParams.count > 1 ? "\(paramName)\(argName.capitalizedFirstLetter)" : paramName } liftedParams.append("\(paramType.swiftType).bridgeJSLiftParameter(\(argNames.joined(separator: ", ")))") } let closureCallExpr = ExprSyntax("closure(\(raw: liftedParams.joined(separator: ", ")))") - let abiReturnWasmType = try signature.returnType.loweringReturnInfo().returnType + let abiReturnWasmType = try signature.returnType.loweringReturnInfo() // Build signature using SwiftSignatureBuilder let funcSignature = SwiftSignatureBuilder.buildABIFunctionSignature( diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index 207f6ee69..8778b7be2 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -20,23 +20,17 @@ import BridgeJSUtilities public class ExportSwift { let progress: ProgressReporting let moduleName: String - private let exposeToGlobal: Bool private var skeleton: ExportedSkeleton - private var sourceFiles: [(sourceFile: SourceFileSyntax, inputFilePath: String)] = [] public init(progress: ProgressReporting, moduleName: String, skeleton: ExportedSkeleton) { self.progress = progress self.moduleName = moduleName - self.exposeToGlobal = skeleton.exposeToGlobal self.skeleton = skeleton } /// Finalizes the export process and generates the bridge code /// - /// - Parameters: - /// - exposeToGlobal: Whether to expose exported APIs to the global namespace (default: false) - /// - Returns: A tuple containing the generated Swift code and a skeleton - /// describing the exported APIs + /// - Returns: The generated Swift glue code, or nil if skeleton is empty public func finalize() throws -> String? { guard let outputSwift = try renderSwiftGlue() else { return nil @@ -101,7 +95,6 @@ public class ExportSwift { var parameters: [Parameter] = [] var abiParameterSignatures: [(name: String, type: WasmCoreType)] = [] var abiReturnType: WasmCoreType? - var externDecls: [DeclSyntax] = [] let effects: Effects init(effects: Effects) { @@ -119,12 +112,12 @@ public class ExportSwift { func liftParameter(param: Parameter) throws { parameters.append(param) - let liftingInfo = try param.type.liftParameterInfo() + let liftingParams = try param.type.liftParameterInfo() let argumentsToLift: [String] - if liftingInfo.parameters.count == 1 { + if liftingParams.count == 1 { argumentsToLift = [param.name] } else { - argumentsToLift = liftingInfo.parameters.map { (name, _) in param.name + name.capitalizedFirstLetter } + argumentsToLift = liftingParams.map { (name, _) in param.name + name.capitalizedFirstLetter } } let typeNameForIntrinsic: String @@ -134,50 +127,37 @@ public class ExportSwift { case .closure(let signature, _): typeNameForIntrinsic = param.type.swiftType liftingExpr = ExprSyntax("_BJS_Closure_\(raw: signature.mangleName).bridgeJSLift(\(raw: param.name))") - case .swiftStruct(let structName): - typeNameForIntrinsic = structName - liftingExpr = ExprSyntax("\(raw: structName).bridgeJSLiftParameter()") case .array: typeNameForIntrinsic = param.type.swiftType liftingExpr = StackCodegen().liftExpression(for: param.type) case .nullable(let wrappedType, let kind): - let optionalSwiftType: String - if case .null = kind { - optionalSwiftType = "Optional" - } else { - optionalSwiftType = "JSUndefinedOr" - } - typeNameForIntrinsic = "\(optionalSwiftType)<\(wrappedType.swiftType)>" + let optionalSwiftType: String = + if case .null = kind { "Optional" } else { "JSUndefinedOr" } + let wrappedName: String = + if case .cast(let name) = wrappedType.descriptor.accessorTransform { name } else { + wrappedType.swiftType + } + typeNameForIntrinsic = "\(optionalSwiftType)<\(wrappedName)>" liftingExpr = ExprSyntax( "\(raw: typeNameForIntrinsic).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" ) default: - typeNameForIntrinsic = param.type.swiftType + if case .cast(let name) = param.type.descriptor.accessorTransform { + typeNameForIntrinsic = name + } else { + typeNameForIntrinsic = param.type.swiftType + } liftingExpr = ExprSyntax( "\(raw: typeNameForIntrinsic).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" ) } liftedParameterExprs.append(liftingExpr) - for (name, type) in zip(argumentsToLift, liftingInfo.parameters.map { $0.type }) { + for (name, type) in zip(argumentsToLift, liftingParams.map { $0.type }) { abiParameterSignatures.append((name, type)) } } - private func protocolCastSuffix(for returnType: BridgeType) -> (prefix: String, suffix: String) { - switch returnType { - case .swiftProtocol: - return ("", " as! \(returnType.swiftType)") - case .nullable(let wrappedType, _): - if case .swiftProtocol = wrappedType { - return ("(", ").flatMap { $0 as? \(wrappedType.swiftType) }") - } - return ("", "") - default: - return ("", "") - } - } - private func removeFirstLiftedParameter() -> (parameter: Parameter, expr: ExprSyntax) { let parameter = parameters.removeFirst() let expr = liftedParameterExprs.removeFirst() @@ -211,10 +191,9 @@ public class ExportSwift { if returnType == .void { return CodeBlockItemSyntax(item: .init(ExpressionStmtSyntax(expression: callExpr))) } else { - let (prefix, suffix) = protocolCastSuffix(for: returnType) - return CodeBlockItemSyntax( - item: .init(DeclSyntax("let ret = \(raw: prefix)\(raw: callExpr)\(raw: suffix)")) - ) + let binding = returnType.descriptor.accessorTransform + .applyToReturnBinding("\(callExpr)", isOptional: returnType.isOptional) + return CodeBlockItemSyntax(item: .init(DeclSyntax("\(raw: binding)"))) } } @@ -228,8 +207,9 @@ public class ExportSwift { if returnType == .void { append("\(raw: name)") } else { - let (prefix, suffix) = protocolCastSuffix(for: returnType) - append("let ret = \(raw: prefix)\(raw: name)\(raw: suffix)") + let binding = returnType.descriptor.accessorTransform + .applyToReturnBinding(name, isOptional: returnType.isOptional) + append("\(raw: binding)") } } @@ -246,14 +226,7 @@ public class ExportSwift { /// Generates intermediate variables for stack-using parameters if needed for LIFO compatibility private func generateParameterLifting() { let stackParamIndices = parameters.enumerated().compactMap { index, param -> Int? in - switch param.type { - case .swiftStruct, .nullable(.swiftStruct, _), - .associatedValueEnum, .nullable(.associatedValueEnum, _), - .array: - return index - default: - return nil - } + param.type.descriptor.usesStackLifting ? index : nil } guard stackParamIndices.count > 1 else { return } @@ -270,11 +243,13 @@ public class ExportSwift { func callPropertyGetter(propertyName: String, returnType: BridgeType) { let (_, selfExpr) = removeFirstLiftedParameter() + let expr = "\(selfExpr).\(propertyName)" if returnType == .void { - append("\(raw: selfExpr).\(raw: propertyName)") + append("\(raw: expr)") } else { - let (prefix, suffix) = protocolCastSuffix(for: returnType) - append("let ret = \(raw: prefix)\(raw: selfExpr).\(raw: propertyName)\(raw: suffix)") + let binding = returnType.descriptor.accessorTransform + .applyToReturnBinding(expr, isOptional: returnType.isOptional) + append("\(raw: binding)") } } @@ -299,8 +274,7 @@ public class ExportSwift { } private func _lowerReturnValue(returnType: BridgeType) throws { - let loweringInfo = try returnType.loweringReturnInfo() - abiReturnType = loweringInfo.returnType + abiReturnType = try returnType.loweringReturnInfo() if returnType == .void { return } @@ -736,10 +710,6 @@ struct StackCodegen { /// - Returns: An ExprSyntax representing the lift expression func liftExpression(for type: BridgeType) -> ExprSyntax { switch type { - case .string, .int, .uint, .bool, .float, .double, - .jsObject(nil), .jsValue, .swiftStruct, .swiftHeapObject, .unsafePointer, - .swiftProtocol, .caseEnum, .associatedValueEnum, .rawValueEnum: - return "\(raw: type.swiftType).bridgeJSStackPop()" case .jsObject(let className?): return "\(raw: className)(unsafelyWrapping: JSObject.bridgeJSStackPop())" case .nullable(let wrappedType, let kind): @@ -748,24 +718,38 @@ struct StackCodegen { return liftArrayExpression(elementType: elementType) case .dictionary(let valueType): return liftDictionaryExpression(valueType: valueType) - case .closure: - return "JSObject.bridgeJSStackPop()" case .void, .namespaceEnum: return "()" + default: + return "\(raw: type.swiftType).bridgeJSStackPop()" } } func liftArrayExpression(elementType: BridgeType) -> ExprSyntax { - switch elementType { - case .jsObject(let className?) where className != "JSObject": + if case .jsObject(let className?) = elementType, className != "JSObject" { return "[JSObject].bridgeJSStackPop().map { \(raw: className)(unsafelyWrapping: $0) }" - case .nullable, .closure: + } + if elementType.needsInlineCollectionHandling { return liftArrayExpressionInline(elementType: elementType) - case .void, .namespaceEnum: - fatalError("Invalid array element type: \(elementType)") - default: - return "[\(raw: elementType.swiftType)].bridgeJSStackPop()" } + return "[\(raw: elementType.swiftType)].bridgeJSStackPop()" + } + + func liftDictionaryExpression(valueType: BridgeType) -> ExprSyntax { + if case .jsObject(let className?) = valueType, className != "JSObject" { + return """ + { + let __dict = [String: JSObject].bridgeJSStackPop() + return __dict.mapValues { \(raw: className)(unsafelyWrapping: $0) } + }() + """ + } + if valueType.needsInlineCollectionHandling { + return liftDictionaryExpressionInline(valueType: valueType) + } + if case .void = valueType { fatalError("Invalid dictionary value type: \(valueType)") } + if case .namespaceEnum = valueType { fatalError("Invalid dictionary value type: \(valueType)") } + return "[String: \(raw: valueType.swiftType)].bridgeJSStackPop()" } private func liftArrayExpressionInline(elementType: BridgeType) -> ExprSyntax { @@ -785,24 +769,6 @@ struct StackCodegen { """ } - func liftDictionaryExpression(valueType: BridgeType) -> ExprSyntax { - switch valueType { - case .jsObject(let className?) where className != "JSObject": - return """ - { - let __dict = [String: JSObject].bridgeJSStackPop() - return __dict.mapValues { \(raw: className)(unsafelyWrapping: $0) } - }() - """ - case .nullable, .closure: - return liftDictionaryExpressionInline(valueType: valueType) - case .void, .namespaceEnum: - fatalError("Invalid dictionary value type: \(valueType)") - default: - return "[String: \(raw: valueType.swiftType)].bridgeJSStackPop()" - } - } - private func liftDictionaryExpressionInline(valueType: BridgeType) -> ExprSyntax { let valueLift = liftExpression(for: valueType) let swiftTypeName = valueType.swiftType @@ -824,14 +790,10 @@ struct StackCodegen { private func liftNullableExpression(wrappedType: BridgeType, kind: JSOptionalKind) -> ExprSyntax { let typeName = kind == .null ? "Optional" : "JSUndefinedOr" switch wrappedType { - case .string, .int, .uint, .bool, .float, .double, .jsObject(nil), .jsValue, - .swiftStruct, .swiftHeapObject, .caseEnum, .associatedValueEnum, .rawValueEnum, - .array, .dictionary: - return "\(raw: typeName)<\(raw: wrappedType.swiftType)>.bridgeJSStackPop()" - case .jsObject(let className?): + case .jsObject(let className?) where className != "JSObject": return "\(raw: typeName).bridgeJSStackPop().map { \(raw: className)(unsafelyWrapping: $0) }" - case .nullable, .void, .namespaceEnum, .closure, .unsafePointer, .swiftProtocol: - fatalError("Invalid nullable wrapped type: \(wrappedType)") + default: + return "\(raw: typeName)<\(raw: wrappedType.swiftType)>.bridgeJSStackPop()" } } @@ -847,24 +809,23 @@ struct StackCodegen { varPrefix: String ) -> [CodeBlockItemSyntax] { switch type { - case .string, .int, .uint, .bool, .float, .double, .jsValue, - .jsObject(nil), .swiftHeapObject, .unsafePointer, .closure, - .caseEnum, .rawValueEnum: - return ["\(raw: accessor).bridgeJSStackPush()"] - case .jsObject(_?): - return ["\(raw: accessor).jsObject.bridgeJSStackPush()"] - case .swiftProtocol: - return ["(\(raw: accessor) as! \(raw: type.swiftType)).bridgeJSStackPush()"] - case .associatedValueEnum, .swiftStruct: - return ["\(raw: accessor).bridgeJSStackPush()"] case .nullable(let wrappedType, _): return lowerOptionalStatements(wrappedType: wrappedType, accessor: accessor, varPrefix: varPrefix) - case .void, .namespaceEnum: - return [] case .array(let elementType): return lowerArrayStatements(elementType: elementType, accessor: accessor, varPrefix: varPrefix) case .dictionary(let valueType): return lowerDictionaryStatements(valueType: valueType, accessor: accessor, varPrefix: varPrefix) + default: + break + } + + let desc = type.descriptor + let transformed = desc.accessorTransform.apply(accessor) + switch desc.lowerMethod { + case .stackReturn, .fullReturn, .pushParameter: + return ["\(raw: transformed).bridgeJSStackPush()"] + case .none: + return [] } } @@ -873,22 +834,32 @@ struct StackCodegen { accessor: String, varPrefix: String ) -> [CodeBlockItemSyntax] { - switch elementType { - case .jsObject(let className?) where className != "JSObject": - return ["\(raw: accessor).map { $0.jsObject }.bridgeJSStackPush()"] - case .swiftProtocol: - return ["\(raw: accessor).map { $0 as! \(raw: elementType.swiftType) }.bridgeJSStackPush()"] - case .nullable, .closure: - return lowerArrayStatementsInline( - elementType: elementType, - accessor: accessor, - varPrefix: varPrefix - ) - case .void, .namespaceEnum: - fatalError("Invalid array element type: \(elementType)") - default: - return ["\(raw: accessor).bridgeJSStackPush()"] + if elementType.needsInlineCollectionHandling { + return lowerArrayStatementsInline(elementType: elementType, accessor: accessor, varPrefix: varPrefix) + } + return lowerCollectionSimple(elementType: elementType, accessor: accessor, mapMethod: "map") + } + + private func lowerDictionaryStatements( + valueType: BridgeType, + accessor: String, + varPrefix: String + ) -> [CodeBlockItemSyntax] { + if valueType.needsInlineCollectionHandling { + return lowerDictionaryStatementsInline(valueType: valueType, accessor: accessor, varPrefix: varPrefix) + } + return lowerCollectionSimple(elementType: valueType, accessor: accessor, mapMethod: "mapValues") + } + + private func lowerCollectionSimple( + elementType: BridgeType, + accessor: String, + mapMethod: String + ) -> [CodeBlockItemSyntax] { + if let mapClosure = elementType.descriptor.accessorTransform.mapClosure { + return ["\(raw: accessor).\(raw: mapMethod) { \(raw: mapClosure) }.bridgeJSStackPush()"] } + return ["\(raw: accessor).bridgeJSStackPush()"] } private func lowerArrayStatementsInline( @@ -915,29 +886,6 @@ struct StackCodegen { return Array(parsed) } - private func lowerDictionaryStatements( - valueType: BridgeType, - accessor: String, - varPrefix: String - ) -> [CodeBlockItemSyntax] { - switch valueType { - case .jsObject(let className?) where className != "JSObject": - return ["\(raw: accessor).mapValues { $0.jsObject }.bridgeJSStackPush()"] - case .swiftProtocol: - return ["\(raw: accessor).mapValues { $0 as! \(raw: valueType.swiftType) }.bridgeJSStackPush()"] - case .nullable, .closure: - return lowerDictionaryStatementsInline( - valueType: valueType, - accessor: accessor, - varPrefix: varPrefix - ) - case .void, .namespaceEnum: - fatalError("Invalid dictionary value type: \(valueType)") - default: - return ["\(raw: accessor).bridgeJSStackPush()"] - } - } - private func lowerDictionaryStatementsInline( valueType: BridgeType, accessor: String, @@ -977,11 +925,8 @@ struct StackCodegen { accessor: String, varPrefix: String ) -> [CodeBlockItemSyntax] { - switch wrappedType { - case .array, .dictionary, .swiftStruct: + if wrappedType.descriptor.optionalConvention == .stackABI { return ["\(raw: accessor).bridgeJSStackPush()"] - default: - break } var statements: [String] = [] @@ -1006,16 +951,12 @@ struct StackCodegen { wrappedType: BridgeType, unwrappedVar: String ) -> [CodeBlockItemSyntax] { - switch wrappedType { - case .jsObject(_?): - return ["\(raw: unwrappedVar).jsObject.bridgeJSStackPush()"] - case .swiftProtocol: - return ["(\(raw: unwrappedVar) as! \(raw: wrappedType.swiftType)).bridgeJSStackPush()"] - case .string, .int, .uint, .bool, .float, .double, .jsValue, - .jsObject(nil), .swiftHeapObject, .unsafePointer, .closure, - .caseEnum, .rawValueEnum, .associatedValueEnum: - return ["\(raw: unwrappedVar).bridgeJSStackPush()"] - default: + let desc = wrappedType.descriptor + let transformed = desc.accessorTransform.apply(unwrappedVar) + switch desc.lowerMethod { + case .stackReturn, .fullReturn, .pushParameter: + return ["\(raw: transformed).bridgeJSStackPush()"] + case .none: return ["preconditionFailure(\"BridgeJS: unsupported optional wrapped type\")"] } } @@ -1243,10 +1184,7 @@ struct StructCodegen { printer.write( multilineString: """ \(accessControl)init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = \(lowerFunctionName)(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + \(lowerFunctionName)(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } """ @@ -1274,7 +1212,7 @@ struct StructCodegen { functionName: lowerFunctionName, signature: SwiftSignatureBuilder.buildABIFunctionSignature( abiParameters: [("objectId", .i32)], - returnType: .i32 + returnType: nil ) ) let liftExternDeclPrinter = CodeFragmentPrinter() @@ -1603,137 +1541,31 @@ extension BridgeType { } } - var isClosureType: Bool { - if case .closure = self { return true } - return false - } - - struct LiftingIntrinsicInfo: Sendable { - let parameters: [(name: String, type: WasmCoreType)] - - static let bool = LiftingIntrinsicInfo(parameters: [("value", .i32)]) - static let int = LiftingIntrinsicInfo(parameters: [("value", .i32)]) - static let float = LiftingIntrinsicInfo(parameters: [("value", .f32)]) - static let double = LiftingIntrinsicInfo(parameters: [("value", .f64)]) - static let string = LiftingIntrinsicInfo(parameters: [("bytes", .i32), ("length", .i32)]) - static let jsObject = LiftingIntrinsicInfo(parameters: [("value", .i32)]) - static let jsValue = LiftingIntrinsicInfo(parameters: [("kind", .i32), ("payload1", .i32), ("payload2", .f64)]) - static let swiftHeapObject = LiftingIntrinsicInfo(parameters: [("value", .pointer)]) - static let unsafePointer = LiftingIntrinsicInfo(parameters: [("pointer", .pointer)]) - static let void = LiftingIntrinsicInfo(parameters: []) - static let caseEnum = LiftingIntrinsicInfo(parameters: [("value", .i32)]) - static let associatedValueEnum = LiftingIntrinsicInfo(parameters: [ - ("caseId", .i32) - ]) - } - - func liftParameterInfo() throws -> LiftingIntrinsicInfo { + func liftParameterInfo() throws -> [(name: String, type: WasmCoreType)] { switch self { - case .bool: return .bool - case .int, .uint: return .int - case .float: return .float - case .double: return .double - case .string: return .string - case .jsObject: return .jsObject - case .jsValue: return .jsValue - case .swiftHeapObject: return .swiftHeapObject - case .unsafePointer: return .unsafePointer - case .swiftProtocol: return .jsObject - case .void: return .void case .nullable(let wrappedType, _): - let wrappedInfo = try wrappedType.liftParameterInfo() - if wrappedInfo.parameters.isEmpty { - return LiftingIntrinsicInfo(parameters: []) + let wrappedParams = try wrappedType.liftParameterInfo() + if wrappedParams.isEmpty { + return [] } var optionalParams: [(name: String, type: WasmCoreType)] = [("isSome", .i32)] - optionalParams.append(contentsOf: wrappedInfo.parameters) - return LiftingIntrinsicInfo(parameters: optionalParams) - case .caseEnum: return .caseEnum - case .rawValueEnum(_, let rawType): - return rawType.liftingIntrinsicInfo - case .associatedValueEnum: - return .associatedValueEnum - case .swiftStruct: - return LiftingIntrinsicInfo(parameters: []) + optionalParams.append(contentsOf: wrappedParams) + return optionalParams case .namespaceEnum: throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters") - case .closure: - return LiftingIntrinsicInfo(parameters: [("callbackId", .i32)]) - case .array, .dictionary: - return LiftingIntrinsicInfo(parameters: []) + default: + return descriptor.wasmParams } } - struct LoweringIntrinsicInfo: Sendable { - let returnType: WasmCoreType? - - static let bool = LoweringIntrinsicInfo(returnType: .i32) - static let int = LoweringIntrinsicInfo(returnType: .i32) - static let float = LoweringIntrinsicInfo(returnType: .f32) - static let double = LoweringIntrinsicInfo(returnType: .f64) - static let string = LoweringIntrinsicInfo(returnType: nil) - static let jsObject = LoweringIntrinsicInfo(returnType: .i32) - static let jsValue = LoweringIntrinsicInfo(returnType: nil) - static let swiftHeapObject = LoweringIntrinsicInfo(returnType: .pointer) - static let unsafePointer = LoweringIntrinsicInfo(returnType: .pointer) - static let void = LoweringIntrinsicInfo(returnType: nil) - static let caseEnum = LoweringIntrinsicInfo(returnType: .i32) - static let rawValueEnum = LoweringIntrinsicInfo(returnType: .i32) - static let associatedValueEnum = LoweringIntrinsicInfo(returnType: nil) - static let swiftStruct = LoweringIntrinsicInfo(returnType: nil) - static let optional = LoweringIntrinsicInfo(returnType: nil) - static let array = LoweringIntrinsicInfo(returnType: nil) - } - - func loweringReturnInfo() throws -> LoweringIntrinsicInfo { + func loweringReturnInfo() throws -> WasmCoreType? { switch self { - case .bool: return .bool - case .int, .uint: return .int - case .float: return .float - case .double: return .double - case .string: return .string - case .jsObject: return .jsObject - case .jsValue: return .jsValue - case .swiftHeapObject: return .swiftHeapObject - case .unsafePointer: return .unsafePointer - case .swiftProtocol: return .jsObject - case .void: return .void - case .nullable: return .optional - case .caseEnum: return .caseEnum - case .rawValueEnum(_, let rawType): - return rawType.loweringIntrinsicInfo - case .associatedValueEnum: - return .associatedValueEnum - case .swiftStruct: - return .swiftStruct + case .nullable: + return nil case .namespaceEnum: throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters") - case .closure: - return .jsObject - case .array, .dictionary: - return .array - } - } -} - -extension SwiftEnumRawType { - var liftingIntrinsicInfo: BridgeType.LiftingIntrinsicInfo { - switch self { - case .bool: return .bool - case .int, .int32, .int64, .uint, .uint32, .uint64: return .int - case .float: return .float - case .double: return .double - case .string: return .string - } - } - - var loweringIntrinsicInfo: BridgeType.LoweringIntrinsicInfo { - switch self { - case .bool: return .bool - case .int, .int32, .int64, .uint, .uint32, .uint64: return .int - case .float: return .float - case .double: return .double - case .string: return .string + default: + return descriptor.wasmReturnType } } } @@ -1765,17 +1597,6 @@ extension DeclModifierSyntax { } } - var isAtLeastPackage: Bool { - switch self.name.tokenKind { - case .keyword(.private): false - case .keyword(.fileprivate): false - case .keyword(.internal): true - case .keyword(.package): true - case .keyword(.public): true - case .keyword(.open): true - default: false - } - } } extension WithModifiersSyntax { diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift index 8eead20b7..078741751 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift @@ -103,31 +103,27 @@ public struct ImportTS { } func lowerParameter(param: Parameter) throws { - let loweringInfo = try param.type.loweringParameterInfo(context: context) + let loweredParams = try param.type.loweringParameterInfo(context: context) switch param.type { case .closure(let signature, useJSTypedClosure: false): let jsTypedClosureType = BridgeType.closure(signature, useJSTypedClosure: true).swiftType body.write("let \(param.name) = \(jsTypedClosureType)(\(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(param.name) default: break } let initializerExpr = ExprSyntax("\(raw: param.name).bridgeJSLowerParameter()") - if loweringInfo.loweredParameters.isEmpty { + if loweredParams.isEmpty { stackLoweringStmts.insert("let _ = \(initializerExpr)", at: 0) return } - // Generate destructured variable names for all lowered parameters - let destructuredNames = loweringInfo.loweredParameters.map { + let destructuredNames = loweredParams.map { "\(param.name)\($0.name.capitalizedFirstLetter)" } - // Always add destructuring statement to body (unified for single and multiple) let pattern: String if destructuredNames.count == 1 { pattern = destructuredNames[0] @@ -138,31 +134,26 @@ public struct ImportTS { body.write("let \(pattern) = \(initializerExpr)") destructuredVarNames.append(contentsOf: destructuredNames) - // Add to signatures and forwardings (unified for both single and multiple) - for (index, (paramName, type)) in loweringInfo.loweredParameters.enumerated() { - // For single parameter, use param.name; for multiple, use constructed name + for (index, (paramName, type)) in loweredParams.enumerated() { let abiParamName: String - if loweringInfo.loweredParameters.count == 1 { + if loweredParams.count == 1 { abiParamName = param.name } else { abiParamName = "\(param.name)\(paramName.capitalizedFirstLetter)" } abiParameterSignatures.append((abiParamName, type)) - - // Always use destructured variable in call without labels - // Swift allows omitting labels when they match parameter names abiParameterForwardings.append(destructuredNames[index]) } } func call(returnType: BridgeType) throws { - let liftingInfo: BridgeType.LiftingReturnInfo = try returnType.liftingReturnInfo(context: context) + let liftingReturn = try returnType.liftingReturnType(context: context) for stmt in stackLoweringStmts { body.write(stmt.description) } let assign = - (returnType == .void || returnType.usesSideChannelForOptionalReturn() || liftingInfo.valueToLift == nil) + (returnType == .void || returnType.usesSideChannelForOptionalReturn || liftingReturn == nil) ? "" : "let ret = " let callExpr = "\(abiName)(\(abiParameterForwardings.joined(separator: ", ")))" @@ -185,25 +176,24 @@ public struct ImportTS { } func liftReturnValue(returnType: BridgeType) throws { - let liftingInfo = try returnType.liftingReturnInfo(context: context) + let liftingReturn = try returnType.liftingReturnType(context: context) if returnType == .void { abiReturnType = nil return } - if returnType.usesSideChannelForOptionalReturn() { - // Side channel returns: extern function returns Void, value is retrieved via side channel + if returnType.usesSideChannelForOptionalReturn { abiReturnType = nil body.write("return \(returnType.swiftType).bridgeJSLiftReturnFromSideChannel()") } else { - abiReturnType = liftingInfo.valueToLift + abiReturnType = liftingReturn let liftExpr: String switch returnType { case .closure(let signature, _): liftExpr = "_BJS_Closure_\(signature.mangleName).bridgeJSLift(ret)" default: - if liftingInfo.valueToLift != nil { + if liftingReturn != nil { liftExpr = "\(returnType.swiftType).bridgeJSLiftReturn(ret)" } else { liftExpr = "\(returnType.swiftType).bridgeJSLiftReturn()" @@ -693,145 +683,42 @@ enum SwiftCodePattern { } extension BridgeType { - struct LoweringParameterInfo { - let loweredParameters: [(name: String, type: WasmCoreType)] - - static let bool = LoweringParameterInfo(loweredParameters: [("value", .i32)]) - static let int = LoweringParameterInfo(loweredParameters: [("value", .i32)]) - static let float = LoweringParameterInfo(loweredParameters: [("value", .f32)]) - static let double = LoweringParameterInfo(loweredParameters: [("value", .f64)]) - static let string = LoweringParameterInfo(loweredParameters: [("value", .i32)]) - static let jsObject = LoweringParameterInfo(loweredParameters: [("value", .i32)]) - static let jsValue = LoweringParameterInfo(loweredParameters: [ - ("kind", .i32), - ("payload1", .i32), - ("payload2", .f64), - ]) - static let void = LoweringParameterInfo(loweredParameters: []) - } - - func loweringParameterInfo(context: BridgeContext = .importTS) throws -> LoweringParameterInfo { + func loweringParameterInfo(context: BridgeContext = .importTS) throws -> [(name: String, type: WasmCoreType)] { switch self { - case .bool: return .bool - case .int, .uint: return .int - case .float: return .float - case .double: return .double - case .string: return .string - case .jsObject: return .jsObject - case .jsValue: return .jsValue - case .void: return .void - case .closure: - // 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: - return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)]) + case .nullable(let wrappedType, _): + let wrappedParams = try wrappedType.loweringParameterInfo(context: context) + return [("isSome", WasmCoreType.i32)] + wrappedParams + case .namespaceEnum: + throw BridgeJSCoreError("Namespace enums cannot be used as parameters") case .swiftProtocol: throw BridgeJSCoreError("swiftProtocol is not supported in imported signatures") - case .caseEnum: - switch context { - case .importTS: - throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") - case .exportSwift: - return LoweringParameterInfo(loweredParameters: [("value", .i32)]) - } - case .rawValueEnum(_, let rawType): - let wasmType = rawType.wasmCoreType ?? .i32 - return LoweringParameterInfo(loweredParameters: [("value", wasmType)]) - case .associatedValueEnum: - switch context { - case .importTS: + case .caseEnum, .associatedValueEnum: + if context == .importTS { throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") - case .exportSwift: - return LoweringParameterInfo(loweredParameters: [("caseId", .i32)]) } - case .swiftStruct: - switch context { - case .importTS: - // Swift structs are bridged as JS objects (object IDs) in imported signatures. - return LoweringParameterInfo(loweredParameters: [("objectId", .i32)]) - case .exportSwift: - return LoweringParameterInfo(loweredParameters: []) - } - case .namespaceEnum: - throw BridgeJSCoreError("Namespace enums cannot be used as parameters") - case .nullable(let wrappedType, _): - let wrappedInfo = try wrappedType.loweringParameterInfo(context: context) - var params = [("isSome", WasmCoreType.i32)] - params.append(contentsOf: wrappedInfo.loweredParameters) - return LoweringParameterInfo(loweredParameters: params) - case .array, .dictionary: - return LoweringParameterInfo(loweredParameters: []) + fallthrough + default: + return descriptor.importParams } } - struct LiftingReturnInfo { - let valueToLift: WasmCoreType? - - static let bool = LiftingReturnInfo(valueToLift: .i32) - static let int = LiftingReturnInfo(valueToLift: .i32) - static let float = LiftingReturnInfo(valueToLift: .f32) - static let double = LiftingReturnInfo(valueToLift: .f64) - static let string = LiftingReturnInfo(valueToLift: .i32) - static let jsObject = LiftingReturnInfo(valueToLift: .i32) - static let jsValue = LiftingReturnInfo(valueToLift: nil) - static let void = LiftingReturnInfo(valueToLift: nil) - } - - func liftingReturnInfo( + func liftingReturnType( context: BridgeContext = .importTS - ) throws -> LiftingReturnInfo { + ) throws -> WasmCoreType? { switch self { - case .bool: return .bool - case .int, .uint: return .int - case .float: return .float - case .double: return .double - case .string: return .string - case .jsObject: return .jsObject - case .jsValue: return .jsValue - case .void: return .void - case .closure: - // JS returns a callback ID for closures, which Swift lifts to a typed closure. - return LiftingReturnInfo(valueToLift: .i32) - case .unsafePointer: - return LiftingReturnInfo(valueToLift: .pointer) - case .swiftHeapObject: - return LiftingReturnInfo(valueToLift: .pointer) + case .nullable(let wrappedType, _): + return try wrappedType.liftingReturnType(context: context) + case .namespaceEnum: + throw BridgeJSCoreError("Namespace enums cannot be used as return values") case .swiftProtocol: throw BridgeJSCoreError("swiftProtocol is not supported in imported signatures") - case .caseEnum: - switch context { - case .importTS: - throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") - case .exportSwift: - return LiftingReturnInfo(valueToLift: .i32) - } - case .rawValueEnum(_, let rawType): - let wasmType = rawType.wasmCoreType ?? .i32 - return LiftingReturnInfo(valueToLift: wasmType) - case .associatedValueEnum: - switch context { - case .importTS: + case .caseEnum, .associatedValueEnum: + if context == .importTS { throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") - case .exportSwift: - return LiftingReturnInfo(valueToLift: .i32) - } - case .swiftStruct: - switch context { - case .importTS: - // Swift structs are bridged as JS objects (object IDs) in imported signatures. - return LiftingReturnInfo(valueToLift: .i32) - case .exportSwift: - return LiftingReturnInfo(valueToLift: nil) } - case .namespaceEnum: - throw BridgeJSCoreError("Namespace enums cannot be used as return values") - case .nullable(let wrappedType, _): - let wrappedInfo = try wrappedType.liftingReturnInfo(context: context) - return LiftingReturnInfo(valueToLift: wrappedInfo.valueToLift) - case .array, .dictionary: - return LiftingReturnInfo(valueToLift: nil) + fallthrough + default: + return descriptor.importReturnType } } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index b779e0171..95989f9cc 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -251,7 +251,7 @@ public struct BridgeJSLink { "let \(JSGlueVariableScope.reservedF32Stack) = [];", "let \(JSGlueVariableScope.reservedF64Stack) = [];", "let \(JSGlueVariableScope.reservedPointerStack) = [];", - "let \(JSGlueVariableScope.reservedTmpStructCleanups) = [];", + "const \(JSGlueVariableScope.reservedEnumHelpers) = {};", "const \(JSGlueVariableScope.reservedStructHelpers) = {};", "", @@ -364,8 +364,9 @@ public struct BridgeJSLink { printer.write( "const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr, len)\(sharedMemory ? ".slice()" : "");" ) - printer.write("const value = \(JSGlueVariableScope.reservedTextDecoder).decode(bytes);") - printer.write("\(JSGlueVariableScope.reservedStringStack).push(value);") + printer.write( + "\(JSGlueVariableScope.reservedStringStack).push(\(JSGlueVariableScope.reservedTextDecoder).decode(bytes));" + ) } printer.write("}") printer.write("bjs[\"swift_js_pop_i32\"] = function() {") @@ -393,38 +394,13 @@ public struct BridgeJSLink { printer.write("return \(JSGlueVariableScope.reservedPointerStack).pop();") } printer.write("}") - printer.write("bjs[\"swift_js_struct_cleanup\"] = function(cleanupId) {") - printer.indent { - printer.write("if (cleanupId === 0) { return; }") - printer.write("const index = (cleanupId | 0) - 1;") - printer.write("const cleanup = \(JSGlueVariableScope.reservedTmpStructCleanups)[index];") - printer.write("\(JSGlueVariableScope.reservedTmpStructCleanups)[index] = null;") - printer.write("if (cleanup) { cleanup(); }") - printer.write( - "while (\(JSGlueVariableScope.reservedTmpStructCleanups).length > 0 && \(JSGlueVariableScope.reservedTmpStructCleanups)[\(JSGlueVariableScope.reservedTmpStructCleanups).length - 1] == null) {" - ) - printer.indent { - printer.write("\(JSGlueVariableScope.reservedTmpStructCleanups).pop();") - } - printer.write("}") - } - printer.write("}") - if !allStructs.isEmpty { for structDef in allStructs { printer.write("bjs[\"swift_js_struct_lower_\(structDef.name)\"] = function(objectId) {") printer.indent { printer.write( - "const { cleanup: cleanup } = \(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lower(\(JSGlueVariableScope.reservedSwift).memory.getObject(objectId));" + "\(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lower(\(JSGlueVariableScope.reservedSwift).memory.getObject(objectId));" ) - printer.write("if (cleanup) {") - printer.indent { - printer.write( - "return \(JSGlueVariableScope.reservedTmpStructCleanups).push(cleanup);" - ) - } - printer.write("}") - printer.write("return 0;") } printer.write("}") @@ -946,14 +922,12 @@ public struct BridgeJSLink { for structDef in allStructs { let structPrinter = CodeFragmentPrinter() let structScope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) - let structCleanup = CodeFragmentPrinter() let fragment = IntrinsicJSFragment.structHelper(structDefinition: structDef, allStructs: allStructs) _ = try fragment.printCode( [structDef.name], IntrinsicJSFragment.PrintCodeContext( scope: structScope, - printer: structPrinter, - cleanupCode: structCleanup + printer: structPrinter ) ) bodyPrinter.write(lines: structPrinter.lines) @@ -965,14 +939,12 @@ public struct BridgeJSLink { for enumDef in allAssocEnums { let enumPrinter = CodeFragmentPrinter() let enumScope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) - let enumCleanup = CodeFragmentPrinter() let fragment = IntrinsicJSFragment.associatedValueEnumHelperFactory(enumDefinition: enumDef) _ = try fragment.printCode( [enumDef.valuesName], IntrinsicJSFragment.PrintCodeContext( scope: enumScope, - printer: enumPrinter, - cleanupCode: enumCleanup + printer: enumPrinter ) ) bodyPrinter.write(lines: enumPrinter.lines) @@ -1068,7 +1040,7 @@ public struct BridgeJSLink { for skeleton in skeletons.compactMap(\.exported) { for enumDef in skeleton.enums where enumDef.enumType == .associatedValue { printer.write( - "const \(enumDef.name)Helpers = __bjs_create\(enumDef.valuesName)Helpers()();" + "const \(enumDef.name)Helpers = __bjs_create\(enumDef.valuesName)Helpers();" ) printer.write("\(JSGlueVariableScope.reservedEnumHelpers).\(enumDef.name) = \(enumDef.name)Helpers;") printer.nextLine() @@ -1084,7 +1056,7 @@ public struct BridgeJSLink { for skeleton in skeletons.compactMap(\.exported) { for structDef in skeleton.structs { printer.write( - "const \(structDef.name)Helpers = __bjs_create\(structDef.name)Helpers()();" + "const \(structDef.name)Helpers = __bjs_create\(structDef.name)Helpers();" ) printer.write( "\(JSGlueVariableScope.reservedStructHelpers).\(structDef.name) = \(structDef.name)Helpers;" @@ -1217,7 +1189,6 @@ public struct BridgeJSLink { class ExportedThunkBuilder { var body: CodeFragmentPrinter - var cleanupCode: CodeFragmentPrinter var parameterForwardings: [String] = [] let effects: Effects let scope: JSGlueVariableScope @@ -1227,11 +1198,9 @@ public struct BridgeJSLink { self.effects = effects self.scope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) self.body = CodeFragmentPrinter() - self.cleanupCode = CodeFragmentPrinter() self.context = IntrinsicJSFragment.PrintCodeContext( scope: scope, printer: body, - cleanupCode: cleanupCode, hasDirectAccessToSwiftClass: hasDirectAccessToSwiftClass ) } @@ -1302,10 +1271,9 @@ public struct BridgeJSLink { ] } - /// Renders the thunk body (body code, cleanup, exception handling, and optional return) into a printer. + /// Renders the thunk body (body code, exception handling, and optional return) into a printer. func renderFunctionBody(into printer: CodeFragmentPrinter, returnExpr: String?) { printer.write(contentsOf: body) - printer.write(contentsOf: cleanupCode) printer.write(lines: checkExceptionLines()) if let returnExpr = returnExpr { printer.write("return \(returnExpr);") @@ -1531,22 +1499,13 @@ public struct BridgeJSLink { let printer = CodeFragmentPrinter() let context = IntrinsicJSFragment.PrintCodeContext( scope: scope, - printer: printer, - cleanupCode: CodeFragmentPrinter() + printer: printer ) let enumValuesName = enumDefinition.valuesName switch enumDefinition.enumType { - case .simple: - let fragment = IntrinsicJSFragment.simpleEnumHelper(enumDefinition: enumDefinition) - _ = try fragment.printCode([enumValuesName], context) - jsTopLevelLines.append(contentsOf: printer.lines) - case .rawValue: - guard enumDefinition.rawType != nil else { - throw BridgeJSLinkError(message: "Raw value enum \(enumDefinition.name) is missing rawType") - } - - let fragment = IntrinsicJSFragment.rawValueEnumHelper(enumDefinition: enumDefinition) + case .simple, .rawValue: + let fragment = IntrinsicJSFragment.caseEnumHelper(enumDefinition: enumDefinition) _ = try fragment.printCode([enumValuesName], context) jsTopLevelLines.append(contentsOf: printer.lines) case .associatedValue: @@ -2117,7 +2076,6 @@ extension BridgeJSLink { class ImportedThunkBuilder { let body: CodeFragmentPrinter let scope: JSGlueVariableScope - let cleanupCode: CodeFragmentPrinter let context: BridgeContext var parameterNames: [String] = [] var parameterForwardings: [String] = [] @@ -2126,12 +2084,10 @@ extension BridgeJSLink { init(context: BridgeContext = .importTS, intrinsicRegistry: JSIntrinsicRegistry) { self.body = CodeFragmentPrinter() self.scope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) - self.cleanupCode = CodeFragmentPrinter() self.context = context self.printContext = IntrinsicJSFragment.PrintCodeContext( scope: scope, - printer: body, - cleanupCode: cleanupCode + printer: body ) } @@ -2175,7 +2131,7 @@ extension BridgeJSLink { printer.write("} catch (error) {") printer.indent { printer.write("setException(error);") - if let abiReturnType = returnType.abiReturnType { + if !returnType.isOptional, let abiReturnType = returnType.descriptor.wasmReturnType { printer.write("return \(abiReturnType.placeholderValue)") } } @@ -2250,7 +2206,7 @@ extension BridgeJSLink { func callPropertyGetter(name: String, returnType: BridgeType) throws -> String? { let objectExpr = "\(JSGlueVariableScope.reservedSwift).memory.getObject(self)" let accessExpr = Self.propertyAccessExpr(objectExpr: objectExpr, propertyName: name) - if context == .exportSwift, returnType.usesSideChannelForOptionalReturn() { + if context == .exportSwift, returnType.usesSideChannelForOptionalReturn { guard case .nullable(let wrappedType, _) = returnType else { fatalError("usesSideChannelForOptionalReturn returned true for non-optional type") } @@ -2670,7 +2626,6 @@ extension BridgeJSLink { getterPrinter.write("get \(property.name)() {") getterPrinter.indent { getterPrinter.write(contentsOf: getterThunkBuilder.body) - getterPrinter.write(contentsOf: getterThunkBuilder.cleanupCode) getterPrinter.write(lines: getterThunkBuilder.checkExceptionLines()) if let returnExpr = getterReturnExpr { getterPrinter.write("return \(returnExpr);") @@ -2698,7 +2653,6 @@ extension BridgeJSLink { setterPrinter.write("set \(property.name)(value) {") setterPrinter.indent { setterPrinter.write(contentsOf: setterThunkBuilder.body) - setterPrinter.write(contentsOf: setterThunkBuilder.cleanupCode) setterPrinter.write(lines: setterThunkBuilder.checkExceptionLines()) } setterPrinter.write("},") diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index da21a6e08..03c0e17bf 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -28,7 +28,7 @@ final class JSGlueVariableScope { static let reservedF32Stack = "f32Stack" static let reservedF64Stack = "f64Stack" static let reservedPointerStack = "ptrStack" - static let reservedTmpStructCleanups = "tmpStructCleanups" + static let reservedEnumHelpers = "enumHelpers" static let reservedStructHelpers = "structHelpers" static let reservedSwiftClosureRegistry = "swiftClosureRegistry" @@ -56,7 +56,6 @@ final class JSGlueVariableScope { reservedF32Stack, reservedF64Stack, reservedPointerStack, - reservedTmpStructCleanups, reservedEnumHelpers, reservedStructHelpers, reservedSwiftClosureRegistry, @@ -84,6 +83,12 @@ final class JSGlueVariableScope { return suffixedName } + func reserveNames(_ names: [String]) { + for name in names { + variables.insert(name) + } + } + func registerIntrinsic(_ name: String, build: (CodeFragmentPrinter) throws -> Void) rethrows { try intrinsicRegistry.register(name: name, build: build) } @@ -109,17 +114,7 @@ extension JSGlueVariableScope { printer.write("\(JSGlueVariableScope.reservedPointerStack).push(\(value));") } - // MARK: Return - - func emitPushI32Return(_ value: String, printer: CodeFragmentPrinter) { - printer.write("\(JSGlueVariableScope.reservedI32Stack).push(\(value));") - } - func emitPushF64Return(_ value: String, printer: CodeFragmentPrinter) { - printer.write("\(JSGlueVariableScope.reservedF64Stack).push(\(value));") - } - func emitPushPointerReturn(_ value: String, printer: CodeFragmentPrinter) { - printer.write("\(JSGlueVariableScope.reservedPointerStack).push(\(value));") - } + // MARK: Pop func popString() -> String { return "\(JSGlueVariableScope.reservedStringStack).pop()" } @@ -147,8 +142,6 @@ struct IntrinsicJSFragment: Sendable { var scope: JSGlueVariableScope /// The printer to print the main fragment code. var printer: CodeFragmentPrinter - /// The printer to print the code that is expected to be executed at the end of the caller of the fragment. - var cleanupCode: CodeFragmentPrinter /// Whether the fragment has direct access to the SwiftHeapObject classes. /// If false, the fragment needs to use `_exports[""]` to access the class. var hasDirectAccessToSwiftClass: Bool = true @@ -204,36 +197,7 @@ struct IntrinsicJSFragment: Sendable { } ) - /// NOTE: JavaScript engine itself converts booleans to integers when passing them to - /// Wasm functions, so we don't need to do anything here - static let boolLowerParameter = identity - static let boolLiftReturn = IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, _ in - return ["\(arguments[0]) !== 0"] - } - ) - static let boolLiftParameter = IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, _ in - return ["\(arguments[0]) !== 0"] - } - ) - static let boolLowerReturn = IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, _ in - return ["\(arguments[0]) ? 1 : 0"] - } - ) - - /// Convert signed Int32 to unsigned for UInt values - static let uintLiftReturn = IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, _ in - return ["\(arguments[0]) >>> 0"] - } - ) - static let uintLiftParameter = uintLiftReturn + // MARK: - String Fragments static let stringLowerParameter = IntrinsicJSFragment( parameters: ["value"], @@ -250,7 +214,7 @@ struct IntrinsicJSFragment: Sendable { static let stringLiftReturn = IntrinsicJSFragment( parameters: [], printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let (scope, printer) = (context.scope, context.printer) let resultLabel = scope.variable("ret") printer.write("const \(resultLabel) = \(JSGlueVariableScope.reservedStorageToReturnString);") printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") @@ -260,11 +224,13 @@ struct IntrinsicJSFragment: Sendable { static let stringLiftParameter = IntrinsicJSFragment( parameters: ["objectId"], printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let (scope, printer) = (context.scope, context.printer) let objectId = arguments[0] let objectLabel = scope.variable("\(objectId)Object") // TODO: Implement "take" operation - printer.write("const \(objectLabel) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(objectId));") + printer.write( + "const \(objectLabel) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(objectId));" + ) printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(objectId));") return [objectLabel] } @@ -272,7 +238,7 @@ struct IntrinsicJSFragment: Sendable { static let stringLowerReturn = IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let printer = context.printer printer.write( "\(JSGlueVariableScope.reservedStorageToReturnBytes) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(arguments[0]));" ) @@ -280,37 +246,32 @@ struct IntrinsicJSFragment: Sendable { } ) + // MARK: - JSObject Fragments + static let jsObjectLowerParameter = IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, _ in return ["swift.memory.retain(\(arguments[0]))"] } ) - static let jsObjectLiftReturn = IntrinsicJSFragment( - parameters: ["retId"], - printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) - // TODO: Implement "take" operation - let resultLabel = scope.variable("ret") - let retId = arguments[0] - printer.write("const \(resultLabel) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(retId));") - printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(retId));") - return [resultLabel] - } - ) - static let jsObjectLiftRetainedObjectId = IntrinsicJSFragment( - parameters: ["objectId"], - printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) - let resultLabel = scope.variable("value") - let objectId = arguments[0] - printer.write( - "const \(resultLabel) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(objectId));" - ) - printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(objectId));") - return [resultLabel] - } - ) + private static func jsObjectTakeRetained(hint: String = "ret") -> IntrinsicJSFragment { + IntrinsicJSFragment( + parameters: ["objectId"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + // TODO: Implement "take" operation + let resultLabel = scope.variable(hint) + let objectId = arguments[0] + printer.write( + "const \(resultLabel) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(objectId));" + ) + printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(objectId));") + return [resultLabel] + } + ) + } + static let jsObjectLiftReturn = jsObjectTakeRetained(hint: "ret") + static let jsObjectLiftRetainedObjectId = jsObjectTakeRetained(hint: "value") static let jsObjectLiftParameter = IntrinsicJSFragment( parameters: ["objectId"], printCode: { arguments, _ in @@ -324,6 +285,8 @@ struct IntrinsicJSFragment: Sendable { } ) + // MARK: - JSValue Fragments + private static let jsValueLowerHelperName = "__bjs_jsValueLower" private static let jsValueLiftHelperName = "__bjs_jsValueLift" @@ -394,7 +357,9 @@ struct IntrinsicJSFragment: Sendable { printer.write("case \"string\":") printer.indent { printer.write("\(kindVar) = 1;") - printer.write("\(payload1Var) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + printer.write( + "\(payload1Var) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));" + ) printer.write("\(payload2Var) = 0;") printer.write("break;") } @@ -408,28 +373,36 @@ struct IntrinsicJSFragment: Sendable { printer.write("case \"object\":") printer.indent { printer.write("\(kindVar) = 3;") - printer.write("\(payload1Var) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + printer.write( + "\(payload1Var) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));" + ) printer.write("\(payload2Var) = 0;") printer.write("break;") } printer.write("case \"function\":") printer.indent { printer.write("\(kindVar) = 3;") - printer.write("\(payload1Var) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + printer.write( + "\(payload1Var) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));" + ) printer.write("\(payload2Var) = 0;") printer.write("break;") } printer.write("case \"symbol\":") printer.indent { printer.write("\(kindVar) = 7;") - printer.write("\(payload1Var) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + printer.write( + "\(payload1Var) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));" + ) printer.write("\(payload2Var) = 0;") printer.write("break;") } printer.write("case \"bigint\":") printer.indent { printer.write("\(kindVar) = 8;") - printer.write("\(payload1Var) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + printer.write( + "\(payload1Var) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));" + ) printer.write("\(payload2Var) = 0;") printer.write("break;") } @@ -446,7 +419,7 @@ struct IntrinsicJSFragment: Sendable { static let jsValueLower = IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let (scope, printer) = (context.scope, context.printer) let value = arguments[0] let kindVar = scope.variable("\(value)Kind") let payload1Var = scope.variable("\(value)Payload1") @@ -528,51 +501,26 @@ struct IntrinsicJSFragment: Sendable { } static func jsValueLowerReturn(context: BridgeContext) -> IntrinsicJSFragment { - switch context { - case .importTS: - // Return values from imported JS functions should be delivered to the Swift side - // via the parameter stacks that `_swift_js_pop_*` read from. - return IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let lowered = try jsValueLower.printCode(arguments, context) - let kindVar = lowered[0] - let payload1Var = lowered[1] - let payload2Var = lowered[2] - scope.emitPushI32Parameter(kindVar, printer: printer) - scope.emitPushI32Parameter(payload1Var, printer: printer) - scope.emitPushF64Parameter(payload2Var, printer: printer) - return [] - } - ) - case .exportSwift: - // Kept for symmetry, though JSValue return for export currently relies on Swift pushing - // to tmpRet stacks directly. - return IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let lowered = try jsValueLower.printCode( - arguments, - context - ) - let kindVar = lowered[0] - let payload1Var = lowered[1] - let payload2Var = lowered[2] - scope.emitPushI32Parameter(kindVar, printer: printer) - scope.emitPushI32Parameter(payload1Var, printer: printer) - scope.emitPushF64Parameter(payload2Var, printer: printer) - return [] - } - ) - } + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let lowered = try jsValueLower.printCode(arguments, context) + let kindVar = lowered[0] + let payload1Var = lowered[1] + let payload2Var = lowered[2] + scope.emitPushI32Parameter(kindVar, printer: printer) + scope.emitPushI32Parameter(payload1Var, printer: printer) + scope.emitPushF64Parameter(payload2Var, printer: printer) + return [] + } + ) } static let jsValueLift = IntrinsicJSFragment( parameters: [], printCode: { _, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let (scope, printer) = (context.scope, context.printer) let payload2 = scope.variable("jsValuePayload2") let payload1 = scope.variable("jsValuePayload1") let kind = scope.variable("jsValueKind") @@ -590,7 +538,7 @@ struct IntrinsicJSFragment: Sendable { static let jsValueLiftParameter = IntrinsicJSFragment( parameters: ["kind", "payload1", "payload2"], printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let (scope, printer) = (context.scope, context.printer) let resultVar = scope.variable("jsValue") registerJSValueHelpers(scope: scope) printer.write( @@ -600,12 +548,17 @@ struct IntrinsicJSFragment: Sendable { } ) - static let swiftHeapObjectLowerParameter = IntrinsicJSFragment( + // MARK: - SwiftHeapObject Fragments + + private static let swiftHeapObjectExtractPointer = IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, context in + printCode: { arguments, _ in return ["\(arguments[0]).pointer"] } ) + static let swiftHeapObjectLowerParameter = swiftHeapObjectExtractPointer + static let swiftHeapObjectLowerReturn = swiftHeapObjectExtractPointer + static func swiftHeapObjectLiftReturn(_ name: String) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["value"], @@ -624,25 +577,19 @@ struct IntrinsicJSFragment: Sendable { } ) } - static let swiftHeapObjectLowerReturn = IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - return ["\(arguments[0]).pointer"] - } - ) + + // MARK: - Associated Enum Fragments static func associatedEnumLowerParameter(enumBase: String) -> IntrinsicJSFragment { IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in - let (printer, cleanup) = (context.printer, context.cleanupCode) + let (scope, printer) = (context.scope, context.printer) let value = arguments[0] - let caseIdName = "\(value)CaseId" - let cleanupName = "\(value)Cleanup" + let caseIdName = scope.variable("\(value)CaseId") printer.write( - "const { caseId: \(caseIdName), cleanup: \(cleanupName) } = \(JSGlueVariableScope.reservedEnumHelpers).\(enumBase).lower(\(value));" + "const \(caseIdName) = \(JSGlueVariableScope.reservedEnumHelpers).\(enumBase).lower(\(value));" ) - cleanup.write("if (\(cleanupName)) { \(cleanupName)(); }") return [caseIdName] } ) @@ -662,435 +609,408 @@ struct IntrinsicJSFragment: Sendable { ) } - static func optionalLiftParameter(wrappedType: BridgeType, kind: JSOptionalKind) throws -> IntrinsicJSFragment { - if case .jsValue = wrappedType { + // MARK: - Optional Handling + + static func optionalLiftParameter( + wrappedType: BridgeType, + kind: JSOptionalKind, + context bridgeContext: BridgeContext = .importTS + ) throws -> IntrinsicJSFragment { + let desc = wrappedType.descriptor + if let glue = desc.jsCoercion, desc.wasmParams.count == 1 { return IntrinsicJSFragment( - parameters: ["isSome", "kind", "payload1", "payload2"], - printCode: { arguments, context in + parameters: ["isSome", "wrappedValue"], + printCode: { arguments, _ in let isSome = arguments[0] - let lifted = try jsValueLiftParameter.printCode( - [arguments[1], arguments[2], arguments[3]], - context - ) - let valueExpr = lifted.first ?? "undefined" - return ["\(isSome) ? \(valueExpr) : null"] + let wrappedValue = arguments[1] + let absenceLiteral = kind.absenceLiteral + if let coerce = glue.liftCoerce { + let coerced = coerce.replacingOccurrences(of: "$0", with: wrappedValue) + return ["\(isSome) ? \(coerced) : \(absenceLiteral)"] + } + return ["\(isSome) ? \(wrappedValue) : \(absenceLiteral)"] } ) } + let innerFragment = try liftParameter(type: wrappedType, context: bridgeContext) + return compositeOptionalLiftParameter( + wrappedType: wrappedType, + kind: kind, + innerFragment: innerFragment + ) + } + + private static func compositeOptionalLiftParameter( + wrappedType: BridgeType, + kind: JSOptionalKind, + innerFragment: IntrinsicJSFragment + ) -> IntrinsicJSFragment { + let desc = wrappedType.descriptor + let isStackConvention = desc.optionalConvention == .stackABI + let absenceLiteral = kind.absenceLiteral + + let outerParams: [String] + if isStackConvention { + outerParams = ["isSome"] + } else { + outerParams = ["isSome"] + innerFragment.parameters + } + return IntrinsicJSFragment( - parameters: ["isSome", "wrappedValue"], + parameters: outerParams, printCode: { arguments, context in let (scope, printer) = (context.scope, context.printer) let isSome = arguments[0] - let wrappedValue = arguments[1] - let resultExpr: String - let absenceLiteral = kind.absenceLiteral - - switch wrappedType { - case .int, .float, .double, .caseEnum: - resultExpr = "\(isSome) ? \(wrappedValue) : \(absenceLiteral)" - case .bool: - resultExpr = "\(isSome) ? \(wrappedValue) !== 0 : \(absenceLiteral)" - case .string: - let objectLabel = scope.variable("obj") - printer.write("let \(objectLabel);") - printer.write("if (\(isSome)) {") - printer.indent { - printer.write( - "\(objectLabel) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(wrappedValue));" - ) - printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(wrappedValue));") - } - printer.write("}") - resultExpr = "\(isSome) ? \(objectLabel) : \(absenceLiteral)" - case .closure: - resultExpr = - "\(isSome) ? \(JSGlueVariableScope.reservedSwift).memory.getObject(\(wrappedValue)) : \(absenceLiteral)" - case .swiftHeapObject(let name): - resultExpr = "\(isSome) ? _exports['\(name)'].__construct(\(wrappedValue)) : \(absenceLiteral)" - case .jsObject: - resultExpr = - "\(isSome) ? \(JSGlueVariableScope.reservedSwift).memory.getObject(\(wrappedValue)) : \(absenceLiteral)" - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - let objectLabel = scope.variable("obj") - printer.write("let \(objectLabel);") - printer.write("if (\(isSome)) {") - printer.indent { - printer.write( - "\(objectLabel) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(wrappedValue));" - ) - printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(wrappedValue));") - } - printer.write("}") - resultExpr = "\(isSome) ? \(objectLabel) : \(absenceLiteral)" - case .bool: - resultExpr = "\(isSome) ? \(wrappedValue) !== 0 : \(absenceLiteral)" - default: - resultExpr = "\(isSome) ? \(wrappedValue) : \(absenceLiteral)" - } - case .associatedValueEnum(let fullName): - let base = fullName.components(separatedBy: ".").last ?? fullName - let enumVar = scope.variable("enumValue") - printer.write("let \(enumVar);") - printer.write("if (\(isSome)) {") - printer.indent { - printer.write( - "\(enumVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(wrappedValue));" - ) - } - printer.write("}") - resultExpr = "\(isSome) ? \(enumVar) : \(absenceLiteral)" - case .swiftStruct(let fullName): - let base = fullName.components(separatedBy: ".").last ?? fullName - let structVar = scope.variable("structValue") - printer.write("let \(structVar);") + let innerArgs = isStackConvention ? [] : Array(arguments.dropFirst()) + + let bufferPrinter = CodeFragmentPrinter() + let innerResults = try innerFragment.printCode( + innerArgs, + context.with(\.printer, bufferPrinter) + ) + + let hasSideEffects = !bufferPrinter.lines.isEmpty + let innerExpr = innerResults.first ?? "undefined" + + if hasSideEffects { + let resultVar = scope.variable("optResult") + printer.write("let \(resultVar);") printer.write("if (\(isSome)) {") printer.indent { - printer.write( - "\(structVar) = \(JSGlueVariableScope.reservedStructHelpers).\(base).lift();" - ) - } - printer.write("} else {") - printer.indent { - printer.write("\(structVar) = \(absenceLiteral);") - } - printer.write("}") - resultExpr = structVar - case .array(let elementType): - let arrayVar = scope.variable("arrayValue") - printer.write("let \(arrayVar);") - printer.write("if (\(isSome)) {") - try printer.indent { - let arrayLiftFragment = try arrayLift(elementType: elementType) - let liftResults = try arrayLiftFragment.printCode([], context) - if let liftResult = liftResults.first { - printer.write("\(arrayVar) = \(liftResult);") + for line in bufferPrinter.lines { + printer.write(line) } + printer.write("\(resultVar) = \(innerExpr);") } printer.write("} else {") printer.indent { - printer.write("\(arrayVar) = \(absenceLiteral);") + printer.write("\(resultVar) = \(absenceLiteral);") } printer.write("}") - resultExpr = arrayVar - case .dictionary(let valueType): - let dictVar = scope.variable("dictValue") - printer.write("let \(dictVar);") - printer.write("if (\(isSome)) {") - try printer.indent { - let dictLiftFragment = try dictionaryLift(valueType: valueType) - let liftResults = try dictLiftFragment.printCode([], context) - if let liftResult = liftResults.first { - printer.write("\(dictVar) = \(liftResult);") - } - } - printer.write("} else {") - printer.indent { - printer.write("\(dictVar) = \(absenceLiteral);") + return [resultVar] + } else { + return ["\(isSome) ? \(innerExpr) : \(absenceLiteral)"] + } + } + ) + } + + static func optionalLowerParameter( + wrappedType: BridgeType, + kind: JSOptionalKind + ) throws -> IntrinsicJSFragment { + let desc = wrappedType.descriptor + if let glue = desc.jsCoercion, desc.wasmParams.count == 1 { + let wasmType = desc.wasmParams[0].type + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let value = arguments[0] + let isSomeVar = scope.variable("isSome") + let presenceExpr = kind.presenceCheck(value: value) + printer.write("const \(isSomeVar) = \(presenceExpr);") + let coerced: String + if let coerce = glue.lowerCoerce { + coerced = coerce.replacingOccurrences(of: "$0", with: value) + } else { + coerced = value } - printer.write("}") - resultExpr = dictVar - default: - resultExpr = "\(isSome) ? \(wrappedValue) : \(absenceLiteral)" + return ["+\(isSomeVar)", "\(isSomeVar) ? \(coerced) : \(wasmType.jsZeroLiteral)"] } + ) + } - return [resultExpr] - } + let innerFragment = try lowerParameter(type: wrappedType) + return try compositeOptionalLowerParameter( + wrappedType: wrappedType, + kind: kind, + innerFragment: innerFragment ) } - static func optionalLowerParameter(wrappedType: BridgeType) throws -> IntrinsicJSFragment { + private static func compositeOptionalLowerParameter( + wrappedType: BridgeType, + kind: JSOptionalKind, + innerFragment: IntrinsicJSFragment + ) throws -> IntrinsicJSFragment { + let desc = wrappedType.descriptor + let isStackConvention = desc.optionalConvention == .stackABI + return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let (scope, printer) = (context.scope, context.printer) let value = arguments[0] + scope.reserveNames(arguments) let isSomeVar = scope.variable("isSome") - printer.write("const \(isSomeVar) = \(value) != null;") + printer.write("const \(isSomeVar) = \(kind.presenceCheck(value: value));") - switch wrappedType { - case .swiftStruct(let fullName): - let base = fullName.components(separatedBy: ".").last ?? fullName - let cleanupVar = scope.variable("\(value)Cleanup") - printer.write("let \(cleanupVar);") - printer.write("if (\(isSomeVar)) {") - printer.indent { - let resultVar = scope.variable("structResult") - printer.write( - "const \(resultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(base).lower(\(value));" - ) - printer.write("\(cleanupVar) = \(resultVar).cleanup;") - } - printer.write("}") - cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") - printer.write("\(JSGlueVariableScope.reservedI32Stack).push(+\(isSomeVar));") - return [] - case .string, .rawValueEnum(_, .string): - let bytesVar = scope.variable("\(value)Bytes") - let idVar = scope.variable("\(value)Id") + let ifBodyPrinter = CodeFragmentPrinter() + let innerResults = try innerFragment.printCode( + [value], + context.with(\.printer, ifBodyPrinter) + ) - printer.write("let \(idVar), \(bytesVar);") - printer.write("if (\(isSomeVar)) {") - printer.indent { - printer.write("\(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));") - printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));") - } - printer.write("}") - return ["+\(isSomeVar)", "\(isSomeVar) ? \(idVar) : 0", "\(isSomeVar) ? \(bytesVar).length : 0"] - case .jsValue: - let lowered = try jsValueLower.printCode([value], context) - return ["+\(isSomeVar)"] + lowered - case .associatedValueEnum(let fullName): - let base = fullName.components(separatedBy: ".").last ?? fullName - let caseIdVar = scope.variable("\(value)CaseId") - let cleanupVar = scope.variable("\(value)Cleanup") - - printer.write("let \(caseIdVar), \(cleanupVar);") - printer.write("if (\(isSomeVar)) {") - printer.indent { - let resultVar = scope.variable("enumResult") - printer.write( - "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(value));" - ) - printer.write("\(caseIdVar) = \(resultVar).caseId;") - printer.write("\(cleanupVar) = \(resultVar).cleanup;") + let resultVars = innerResults.map { _ in scope.variable("result") } + for resultVar in resultVars { + printer.write("let \(resultVar);") + } + + printer.write("if (\(isSomeVar)) {") + printer.indent { + for line in ifBodyPrinter.lines { + printer.write(line) } - printer.write("}") - cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") - - return ["+\(isSomeVar)", "\(isSomeVar) ? \(caseIdVar) : 0"] - case .rawValueEnum: - // Raw value enums with optional - falls through to handle based on raw type - return ["+\(isSomeVar)", "\(isSomeVar) ? \(value) : 0"] - case .array(let elementType): - let cleanupArrayVar = scope.variable("\(value)Cleanups") - printer.write("const \(cleanupArrayVar) = [];") - printer.write("if (\(isSomeVar)) {") - try printer.indent { - let arrayLowerFragment = try arrayLower(elementType: elementType) - let arrayCleanup = CodeFragmentPrinter() - let _ = try arrayLowerFragment.printCode( - [value], - context.with(\.cleanupCode, arrayCleanup) - ) - if !arrayCleanup.lines.isEmpty { - for line in arrayCleanup.lines { - printer.write("\(cleanupArrayVar).push(() => { \(line) });") - } - } + for (resultVar, innerResult) in zip(resultVars, innerResults) { + printer.write("\(resultVar) = \(innerResult);") } - printer.write("}") - cleanupCode.write("for (const cleanup of \(cleanupArrayVar)) { cleanup(); }") - printer.write("\(JSGlueVariableScope.reservedI32Stack).push(+\(isSomeVar));") - return [] - case .dictionary(let valueType): - let cleanupArrayVar = scope.variable("\(value)Cleanups") - printer.write("const \(cleanupArrayVar) = [];") - printer.write("if (\(isSomeVar)) {") - try printer.indent { - let dictLowerFragment = try dictionaryLower(valueType: valueType) - let dictCleanup = CodeFragmentPrinter() - let _ = try dictLowerFragment.printCode( - [value], - context.with(\.cleanupCode, dictCleanup) - ) - if !dictCleanup.lines.isEmpty { - for line in dictCleanup.lines { - printer.write("\(cleanupArrayVar).push(() => { \(line) });") - } + } + + let hasPlaceholders = !isStackConvention && !desc.wasmParams.isEmpty + if hasPlaceholders { + printer.write("} else {") + printer.indent { + for (resultVar, param) in zip(resultVars, desc.wasmParams) { + printer.write("\(resultVar) = \(param.type.jsZeroLiteral);") } } - printer.write("}") - cleanupCode.write("for (const cleanup of \(cleanupArrayVar)) { cleanup(); }") - printer.write("\(JSGlueVariableScope.reservedI32Stack).push(+\(isSomeVar));") + } + printer.write("}") + + if isStackConvention { + scope.emitPushI32Parameter("+\(isSomeVar)", printer: printer) return [] - default: - switch wrappedType { - case .swiftHeapObject: - return ["+\(isSomeVar)", "\(isSomeVar) ? \(value).pointer : 0"] - case .swiftProtocol: - return [ - "+\(isSomeVar)", - "\(isSomeVar) ? \(JSGlueVariableScope.reservedSwift).memory.retain(\(value)) : 0", - ] - case .jsObject: - let idVar = scope.variable("id") - printer.write("let \(idVar);") - printer.write("if (\(isSomeVar)) {") - printer.indent { - printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") - } - printer.write("}") - return ["+\(isSomeVar)", "\(isSomeVar) ? \(idVar) : 0"] - default: - return ["+\(isSomeVar)", "\(isSomeVar) ? \(value) : 0"] - } + } else { + return ["+\(isSomeVar)"] + resultVars } } ) } - static func optionalLiftReturn( - wrappedType: BridgeType, - kind: JSOptionalKind - ) -> IntrinsicJSFragment { - let absenceLiteral = kind.absenceLiteral - return IntrinsicJSFragment( + private static func optionalLiftReturnFromStorage(storage: String) -> IntrinsicJSFragment { + IntrinsicJSFragment( parameters: [], - printCode: { arguments, context in + printCode: { _, context in let (scope, printer) = (context.scope, context.printer) let resultVar = scope.variable("optResult") - switch wrappedType { - case .bool: - printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalBool);") - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalBool) = undefined;") - case .int, .uint: - printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalInt);") - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = undefined;") - case .float: - printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalFloat);") - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = undefined;") - case .double: - printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalDouble);") - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = undefined;") - case .string: - printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnString);") - printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") - case .jsObject, .swiftProtocol: - printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnString);") - printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") - case .swiftHeapObject(let className): - let pointerVar = scope.variable("pointer") - printer.write( - "const \(pointerVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject);" - ) - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject) = undefined;") - let constructExpr = - context.hasDirectAccessToSwiftClass - ? "\(className).__construct(\(pointerVar))" - : "_exports['\(className)'].__construct(\(pointerVar))" + printer.write("const \(resultVar) = \(storage);") + printer.write("\(storage) = undefined;") + return [resultVar] + } + ) + } + + private static func optionalLiftReturnWithPresenceFlag( + wrappedType: BridgeType, + kind: JSOptionalKind + ) -> IntrinsicJSFragment { + let absenceLiteral = kind.absenceLiteral + return IntrinsicJSFragment( + parameters: [], + printCode: { _, context in + let (scope, printer) = (context.scope, context.printer) + let isSomeVar = scope.variable("isSome") + printer.write("const \(isSomeVar) = \(scope.popI32());") + + let innerFragment = try liftReturn(type: wrappedType) + + let innerPrinter = CodeFragmentPrinter() + let innerResults = try innerFragment.printCode([], context.with(\.printer, innerPrinter)) + let innerExpr = innerResults.first ?? "undefined" + + if innerPrinter.lines.isEmpty { + return ["\(isSomeVar) ? \(innerExpr) : \(absenceLiteral)"] + } + + let resultVar = scope.variable("optResult") + printer.write("let \(resultVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + for line in innerPrinter.lines { + printer.write(line) + } + printer.write("\(resultVar) = \(innerExpr);") + } + printer.write("} else {") + printer.indent { + printer.write("\(resultVar) = \(absenceLiteral);") + } + printer.write("}") + return [resultVar] + } + ) + } + + private static func optionalLiftReturnAssociatedEnum( + fullName: String, + kind: JSOptionalKind + ) -> IntrinsicJSFragment { + let base = fullName.components(separatedBy: ".").last ?? fullName + let absenceLiteral = kind.absenceLiteral + return IntrinsicJSFragment( + parameters: [], + printCode: { _, context in + let (scope, printer) = (context.scope, context.printer) + let resultVar = scope.variable("optResult") + let tagVar = scope.variable("tag") + printer.write("const \(tagVar) = \(scope.popI32());") + printer.write( + "const \(resultVar) = \(tagVar) === -1 ? \(absenceLiteral) : \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(tagVar));" + ) + return [resultVar] + } + ) + } + + private static func optionalLiftReturnHeapObject( + className: String, + kind: JSOptionalKind + ) -> IntrinsicJSFragment { + let absenceLiteral = kind.absenceLiteral + return IntrinsicJSFragment( + parameters: [], + printCode: { _, context in + let (scope, printer) = (context.scope, context.printer) + let resultVar = scope.variable("optResult") + let pointerVar = scope.variable("pointer") + printer.write( + "const \(pointerVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject);" + ) + printer.write( + "\(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject) = undefined;" + ) + let constructExpr = + context.hasDirectAccessToSwiftClass + ? "\(className).__construct(\(pointerVar))" + : "_exports['\(className)'].__construct(\(pointerVar))" + printer.write( + "const \(resultVar) = \(pointerVar) === null ? \(absenceLiteral) : \(constructExpr);" + ) + return [resultVar] + } + ) + } + + private static func optionalLiftReturnStruct( + fullName: String, + kind: JSOptionalKind + ) -> IntrinsicJSFragment { + let base = fullName.components(separatedBy: ".").last ?? fullName + let absenceLiteral = kind.absenceLiteral + return IntrinsicJSFragment( + parameters: [], + printCode: { _, context in + let (scope, printer) = (context.scope, context.printer) + let isSomeVar = scope.variable("isSome") + let resultVar = scope.variable("optResult") + printer.write("const \(isSomeVar) = \(scope.popI32());") + printer.write( + "const \(resultVar) = \(isSomeVar) ? \(JSGlueVariableScope.reservedStructHelpers).\(base).lift() : \(absenceLiteral);" + ) + return [resultVar] + } + ) + } + + static func optionalLiftReturn( + wrappedType: BridgeType, + kind: JSOptionalKind + ) -> IntrinsicJSFragment { + let desc = wrappedType.descriptor + if let glue = desc.jsCoercion, let kind = glue.optionalScalarKind { + return optionalLiftReturnFromStorage(storage: kind.storageName) + } + if case .sideChannelReturn(let mode) = desc.optionalConvention, mode != .none { + return optionalLiftReturnFromStorage(storage: JSGlueVariableScope.reservedStorageToReturnString) + } + + if case .swiftHeapObject(let className) = wrappedType { + return optionalLiftReturnHeapObject(className: className, kind: kind) + } + + if case .swiftStruct(let fullName) = wrappedType { + return optionalLiftReturnStruct(fullName: fullName, kind: kind) + } + + if desc.nilSentinel.hasSentinel, case .associatedValueEnum(let fullName) = wrappedType { + return optionalLiftReturnAssociatedEnum(fullName: fullName, kind: kind) + } + + return optionalLiftReturnWithPresenceFlag(wrappedType: wrappedType, kind: kind) + } + + private static func optionalLowerReturnToSideChannel( + mode: OptionalSideChannel, + kind: JSOptionalKind + ) -> IntrinsicJSFragment { + IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let value = arguments[0] + let isSomeVar = scope.variable("isSome") + let presenceExpr = kind.presenceCheck(value: value) + printer.write("const \(isSomeVar) = \(presenceExpr);") + + if mode == .storage { printer.write( - "const \(resultVar) = \(pointerVar) === null ? \(absenceLiteral) : \(constructExpr);" + "\(JSGlueVariableScope.reservedStorageToReturnString) = \(isSomeVar) ? \(value) : \(kind.absenceLiteral);" ) - case .caseEnum: - printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalInt);") - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = undefined;") - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnString);") - printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") - case .bool: - printer.write( - "const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalBool);" - ) - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalBool) = undefined;") - case .float: - printer.write( - "const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalFloat);" - ) - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = undefined;") - case .double: - printer.write( - "const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalDouble);" - ) - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = undefined;") - default: - printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalInt);") - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = undefined;") - } - case .associatedValueEnum(let fullName): - let base = fullName.components(separatedBy: ".").last ?? fullName - let tagVar = scope.variable("tag") - printer.write("const \(tagVar) = \(scope.popI32());") - let isNullVar = scope.variable("isNull") - printer.write("const \(isNullVar) = (\(tagVar) === -1);") - printer.write("let \(resultVar);") - printer.write("if (\(isNullVar)) {") - printer.indent { - printer.write("\(resultVar) = \(absenceLiteral);") - } - printer.write("} else {") - printer.indent { - printer.write( - "\(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(tagVar));" - ) - } - printer.write("}") - case .swiftStruct(let fullName): - let base = fullName.components(separatedBy: ".").last ?? fullName - let isSomeVar = scope.variable("isSome") - printer.write("const \(isSomeVar) = \(scope.popI32());") - printer.write("let \(resultVar);") + } else { + let idVar = scope.variable("id") + printer.write("let \(idVar) = 0;") printer.write("if (\(isSomeVar)) {") printer.indent { printer.write( - "\(resultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(base).lift();" + "\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));" ) } - printer.write("} else {") - printer.indent { - printer.write("\(resultVar) = \(absenceLiteral);") - } - printer.write("}") - case .array(let elementType): - let isSomeVar = scope.variable("isSome") - printer.write("const \(isSomeVar) = \(scope.popI32());") - printer.write("let \(resultVar);") - printer.write("if (\(isSomeVar)) {") - try printer.indent { - let arrayLiftFragment = try arrayLift(elementType: elementType) - let liftResults = try arrayLiftFragment.printCode([], context) - if let liftResult = liftResults.first { - printer.write("\(resultVar) = \(liftResult);") - } - } - printer.write("} else {") - printer.indent { - printer.write("\(resultVar) = \(absenceLiteral);") - } printer.write("}") - case .dictionary(let valueType): - let isSomeVar = scope.variable("isSome") - printer.write("const \(isSomeVar) = \(scope.popI32());") - printer.write("let \(resultVar);") - printer.write("if (\(isSomeVar)) {") - try printer.indent { - let dictLiftFragment = try dictionaryLift(valueType: valueType) - let liftResults = try dictLiftFragment.printCode([], context) - if let liftResult = liftResults.first { - printer.write("\(resultVar) = \(liftResult);") - } - } - printer.write("} else {") - printer.indent { - printer.write("\(resultVar) = \(absenceLiteral);") - } - printer.write("}") - case .jsValue: - let isSomeVar = scope.variable("isSome") - printer.write("const \(isSomeVar) = \(scope.popI32());") - printer.write("let \(resultVar);") - printer.write("if (\(isSomeVar)) {") - try printer.indent { - let lifted = try jsValueLift.printCode([], context) - if let liftedValue = lifted.first { - printer.write("\(resultVar) = \(liftedValue);") - } - } - printer.write("} else {") - printer.indent { - printer.write("\(resultVar) = null;") + printer.write("bjs[\"swift_js_return_optional_object\"](\(isSomeVar) ? 1 : 0, \(idVar));") + } + + return [] + } + ) + } + + private static func optionalLowerReturnWithPresenceFlag( + wrappedType: BridgeType, + kind: JSOptionalKind, + innerFragment: IntrinsicJSFragment + ) -> IntrinsicJSFragment { + IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let value = arguments[0] + let isSomeVar = scope.variable("isSome") + let presenceExpr = kind.presenceCheck(value: value) + printer.write("const \(isSomeVar) = \(presenceExpr);") + + let innerPrinter = CodeFragmentPrinter() + let innerResults = try innerFragment.printCode( + [value], + context.with(\.printer, innerPrinter) + ) + if !innerResults.isEmpty { + throw BridgeJSLinkError( + message: "Unsupported wrapped type for returning from JS function: \(wrappedType)" + ) + } + + printer.write("if (\(isSomeVar)) {") + printer.indent { + for line in innerPrinter.lines { + printer.write(line) } - printer.write("}") - default: - printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnString);") - printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") } - return [resultVar] + printer.write("}") + + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + return [] } ) } @@ -1102,188 +1022,106 @@ struct IntrinsicJSFragment: Sendable { default: break } + let desc = wrappedType.descriptor + if let glue = desc.jsCoercion, let scalarKind = glue.optionalScalarKind, + !desc.nilSentinel.hasSentinel, desc.wasmParams.count == 1 + { + let wasmType = desc.wasmParams[0].type + let funcName = scalarKind.funcName + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let value = arguments[0] + let isSomeVar = scope.variable("isSome") + let presenceExpr = kind.presenceCheck(value: value) + printer.write("const \(isSomeVar) = \(presenceExpr);") + var coerced: String + if let coerce = glue.effectiveStackLowerCoerce { + coerced = coerce.replacingOccurrences(of: "$0", with: value) + if coerced.contains("?") && !coerced.hasPrefix("(") { + coerced = "(\(coerced))" + } + } else { + coerced = value + } + printer.write( + "bjs[\"\(funcName)\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? \(coerced) : \(wasmType.jsZeroLiteral));" + ) + return [] + } + ) + } + + if case .sideChannelReturn(let mode) = desc.optionalConvention { + if mode == .none { + throw BridgeJSLinkError( + message: "Unsupported wrapped type for returning from JS function: \(wrappedType)" + ) + } + return optionalLowerReturnToSideChannel(mode: mode, kind: kind) + } + + if desc.nilSentinel.hasSentinel { + let innerFragment = try lowerReturn(type: wrappedType, context: .exportSwift) + return sentinelOptionalLowerReturn( + wrappedType: wrappedType, + kind: kind, + innerFragment: innerFragment + ) + } + + let innerFragment = try lowerReturn(type: wrappedType, context: .exportSwift) + return optionalLowerReturnWithPresenceFlag( + wrappedType: wrappedType, + kind: kind, + innerFragment: innerFragment + ) + } + + private static func sentinelOptionalLowerReturn( + wrappedType: BridgeType, + kind: JSOptionalKind, + innerFragment: IntrinsicJSFragment + ) -> IntrinsicJSFragment { + let desc = wrappedType.descriptor + let sentinelLiteral = desc.nilSentinel.jsLiteral + return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let (scope, printer) = (context.scope, context.printer) let value = arguments[0] let isSomeVar = scope.variable("isSome") let presenceExpr = kind.presenceCheck(value: value) printer.write("const \(isSomeVar) = \(presenceExpr);") - switch wrappedType { - case .bool: - printer.write( - "bjs[\"swift_js_return_optional_bool\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? (\(value) ? 1 : 0) : 0);" - ) - case .int, .uint: - printer.write( - "bjs[\"swift_js_return_optional_int\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? (\(value) | 0) : 0);" - ) - case .caseEnum: - printer.write("return \(isSomeVar) ? (\(value) | 0) : -1;") - case .float: - printer.write( - "bjs[\"swift_js_return_optional_float\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? Math.fround(\(value)) : 0.0);" - ) - case .double: - printer.write( - "bjs[\"swift_js_return_optional_double\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? \(value) : 0.0);" - ) - case .string: - printer.write("if (\(isSomeVar)) {") - printer.indent { - printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = \(value);") - } - printer.write("} else {") - printer.indent { - printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = null;") - } - printer.write("}") - case .jsObject, .swiftProtocol: - let idVar = scope.variable("id") - printer.write("let \(idVar) = 0;") + let bufferPrinter = CodeFragmentPrinter() + let innerResults = try innerFragment.printCode( + [value], + context.with(\.printer, bufferPrinter) + ) + + let hasSideEffects = !bufferPrinter.lines.isEmpty + let innerExpr = innerResults.first + + if hasSideEffects { printer.write("if (\(isSomeVar)) {") printer.indent { - printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") - } - printer.write("}") - printer.write("bjs[\"swift_js_return_optional_object\"](\(isSomeVar) ? 1 : 0, \(idVar));") - case .jsValue: - if value != "undefined" { - let lowered = try jsValueLower.printCode([value], context) - let kindVar = lowered[0] - let payload1Var = lowered[1] - let payload2Var = lowered[2] - scope.emitPushI32Parameter(kindVar, printer: printer) - scope.emitPushI32Parameter(payload1Var, printer: printer) - scope.emitPushF64Parameter(payload2Var, printer: printer) - } - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - case .swiftHeapObject: - printer.write("return \(isSomeVar) ? \(value).pointer : 0;") - case .array(let elementType): - printer.write("if (\(isSomeVar)) {") - try printer.indent { - let arrayLowerFragment = try arrayLower(elementType: elementType) - let arrayCleanup = CodeFragmentPrinter() - let _ = try arrayLowerFragment.printCode( - [value], - context.with(\.cleanupCode, arrayCleanup) - ) - if !arrayCleanup.lines.isEmpty { - for line in arrayCleanup.lines { - printer.write(line) - } - } - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - printer.write("if (\(isSomeVar)) {") - printer.indent { - printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = \(value);") - } - printer.write("} else {") - printer.indent { - printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = null;") + for line in bufferPrinter.lines { + printer.write(line) } - printer.write("}") - default: - switch rawType { - case .bool: - printer.write( - "bjs[\"swift_js_return_optional_bool\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? (\(value) ? 1 : 0) : 0);" - ) - case .float: - printer.write( - "bjs[\"swift_js_return_optional_float\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? Math.fround(\(value)) : 0.0);" - ) - case .double: - printer.write( - "bjs[\"swift_js_return_optional_double\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? \(value) : 0.0);" - ) - default: - printer.write( - "bjs[\"swift_js_return_optional_int\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? (\(value) | 0) : 0);" - ) + if let expr = innerExpr { + printer.write("return \(expr);") } } - case .associatedValueEnum(let fullName): - let base = fullName.components(separatedBy: ".").last ?? fullName - let caseIdVar = scope.variable("caseId") - let cleanupVar = scope.variable("cleanup") - printer.write("if (\(isSomeVar)) {") - printer.indent { - printer.write( - "const { caseId: \(caseIdVar), cleanup: \(cleanupVar) } = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(value));" - ) - printer.write("return \(caseIdVar);") - } printer.write("} else {") printer.indent { - printer.write("return -1;") + printer.write("return \(sentinelLiteral);") } printer.write("}") - cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") - case .dictionary(let valueType): - printer.write("if (\(isSomeVar)) {") - try printer.indent { - let cleanupArrayVar = scope.variable("arrayCleanups") - let entriesVar = scope.variable("entries") - let entryVar = scope.variable("entry") - printer.write("const \(cleanupArrayVar) = [];") - printer.write("const \(entriesVar) = Object.entries(\(value));") - printer.write("for (const \(entryVar) of \(entriesVar)) {") - try printer.indent { - let keyVar = scope.variable("key") - let valueVar = scope.variable("value") - printer.write("const [\(keyVar), \(valueVar)] = \(entryVar);") - - let keyFragment = try stackLowerFragment(elementType: .string) - let keyCleanup = CodeFragmentPrinter() - let _ = try keyFragment.printCode( - [keyVar], - context.with(\.cleanupCode, keyCleanup) - ) - if !keyCleanup.lines.isEmpty { - printer.write("\(cleanupArrayVar).push(() => {") - printer.indent { - for line in keyCleanup.lines { - printer.write(line) - } - } - printer.write("});") - } - - let valueFragment = try stackLowerFragment(elementType: valueType) - let valueCleanup = CodeFragmentPrinter() - let _ = try valueFragment.printCode( - [valueVar], - context.with(\.cleanupCode, valueCleanup) - ) - if !valueCleanup.lines.isEmpty { - printer.write("\(cleanupArrayVar).push(() => {") - printer.indent { - for line in valueCleanup.lines { - printer.write(line) - } - } - printer.write("});") - } - } - printer.write("}") - scope.emitPushI32Parameter("\(entriesVar).length", printer: printer) - cleanupCode.write("for (const cleanup of \(cleanupArrayVar)) { cleanup(); }") - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - default: - throw BridgeJSLinkError( - message: "Unsupported wrapped type for returning from JS function: \(wrappedType)" - ) + } else if let expr = innerExpr { + printer.write("return \(isSomeVar) ? \(expr) : \(sentinelLiteral);") } return [] @@ -1294,71 +1132,188 @@ struct IntrinsicJSFragment: Sendable { // MARK: - Protocol Support static func protocolPropertyOptionalToSideChannel(wrappedType: BridgeType) throws -> IntrinsicJSFragment { - switch wrappedType { - case .string, .int, .float, .double, .jsObject, .swiftProtocol: - break - case .rawValueEnum(_, let rawType): - switch rawType { - case .string, .int, .float, .double: - break - default: - throw BridgeJSLinkError( - message: "Unsupported raw value enum type for protocol property side channel: \(rawType)" - ) - } - default: - throw BridgeJSLinkError( - message: "Type \(wrappedType) does not use side channel for protocol property returns" + let desc = wrappedType.descriptor + if let glue = desc.jsCoercion, let scalarKind = glue.optionalScalarKind { + let storage = scalarKind.storageName + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + context.printer.write("\(storage) = \(arguments[0]);") + return [] + } ) } - return IntrinsicJSFragment( + if case .sideChannelReturn(let mode) = desc.optionalConvention, + mode != .none + { + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let printer = context.printer + let value = arguments[0] + + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = \(value);") + + return [] + } + ) + } + + throw BridgeJSLinkError( + message: "Type \(wrappedType) does not use side channel for protocol property returns" + ) + } + + // MARK: - JS Glue Descriptor Helpers + + private static func popExpression(for wasmType: WasmCoreType, scope: JSGlueVariableScope) -> String { + switch wasmType { + case .i32: return scope.popI32() + case .f32: return scope.popF32() + case .f64: return scope.popF64() + case .pointer: return scope.popPointer() + case .i64: return scope.popI32() + } + } + + private static func emitPush( + for wasmType: WasmCoreType, + value: String, + scope: JSGlueVariableScope, + printer: CodeFragmentPrinter + ) { + switch wasmType { + case .i32: scope.emitPushI32Parameter(value, printer: printer) + case .f32: scope.emitPushF32Parameter(value, printer: printer) + case .f64: scope.emitPushF64Parameter(value, printer: printer) + case .pointer: scope.emitPushPointerParameter(value, printer: printer) + case .i64: scope.emitPushI32Parameter(value, printer: printer) + } + } + + @discardableResult + private static func emitOptionalPlaceholders( + for wrappedType: BridgeType, + scope: JSGlueVariableScope, + printer: CodeFragmentPrinter + ) -> Bool { + let desc = wrappedType.descriptor + let params = desc.wasmParams + if params.isEmpty { + return false + } + for param in params { + emitPush(for: param.type, value: param.type.jsZeroLiteral, scope: scope, printer: printer) + } + return true + } + + private static func stackOptionalLower( + wrappedType: BridgeType, + kind: JSOptionalKind, + innerFragment: IntrinsicJSFragment + ) -> IntrinsicJSFragment { + IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in - let printer = context.printer + let (scope, printer) = (context.scope, context.printer) let value = arguments[0] + let isSomeVar = scope.variable("isSome") + printer.write("const \(isSomeVar) = \(kind.presenceCheck(value: value));") - switch wrappedType { - case .string, .rawValueEnum(_, .string): - printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = \(value);") - case .int, .rawValueEnum(_, .int): - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = \(value);") - case .float, .rawValueEnum(_, .float): - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = \(value);") - case .double, .rawValueEnum(_, .double): - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = \(value);") - case .jsObject, .swiftProtocol: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = \(value);") - default: - fatalError("Unsupported type in protocolPropertyOptionalToSideChannel: \(wrappedType)") + let ifBodyPrinter = CodeFragmentPrinter() + try ifBodyPrinter.indent { + let _ = try innerFragment.printCode( + [value], + context.with(\.printer, ifBodyPrinter) + ) + } + printer.write("if (\(isSomeVar)) {") + for line in ifBodyPrinter.lines { + printer.write(line) + } + let placeholderPrinter = CodeFragmentPrinter() + let hasPlaceholders = emitOptionalPlaceholders( + for: wrappedType, + scope: scope, + printer: placeholderPrinter + ) + if hasPlaceholders { + printer.write("} else {") + printer.indent { + for line in placeholderPrinter.lines { + printer.write(line) + } + } + printer.write("}") + } else { + printer.write("}") + } + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + return [] + } + ) + } + + /// Builds lift/lower fragments from a type's scalar coercion info. + /// Returns `nil` when the type has no scalar coercion (complex types) or when + /// the type is nullable/indirect (optionals need dedicated handling). + /// + /// For scalar types, `lowerParameter` is always `.identity` (JS auto-coerces) + /// and `liftReturn`/`liftParameter` share the same lift fragment. + private static func scalarFragments( + for type: BridgeType + ) -> ( + lift: IntrinsicJSFragment, + lower: IntrinsicJSFragment + )? { + if case .nullable = type { return nil } + let desc = type.descriptor + guard let coercion = desc.jsCoercion else { return nil } + + let liftFragment: IntrinsicJSFragment + if let coerce = coercion.liftCoerce { + liftFragment = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, _ in + return [coerce.replacingOccurrences(of: "$0", with: arguments[0])] + } + ) + } else { + liftFragment = .identity + } + + let lowerFragment: IntrinsicJSFragment + if let coerce = coercion.lowerCoerce { + lowerFragment = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, _ in + return [coerce.replacingOccurrences(of: "$0", with: arguments[0])] } + ) + } else { + lowerFragment = .identity + } - return [] - } - ) + return (lift: liftFragment, lower: lowerFragment) } // MARK: - ExportSwift /// Returns a fragment that lowers a JS value to Wasm core values for parameters static func lowerParameter(type: BridgeType) throws -> IntrinsicJSFragment { + if scalarFragments(for: type) != nil { return .identity } switch type { - case .int, .uint, .float, .double, .bool, .unsafePointer: return .identity case .string: return .stringLowerParameter case .jsObject: return .jsObjectLowerParameter case .jsValue: return .jsValueLower - case .swiftHeapObject: - return .swiftHeapObjectLowerParameter + case .swiftHeapObject: return .swiftHeapObjectLowerParameter case .swiftProtocol: return .jsObjectLowerParameter case .void: return .void - case .nullable(let wrappedType, _): - return try .optionalLowerParameter(wrappedType: wrappedType) - case .caseEnum: return .identity - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: return .stringLowerParameter - default: return .identity - } + case .nullable(let wrappedType, let kind): + return try .optionalLowerParameter(wrappedType: wrappedType, kind: kind) + case .rawValueEnum(_, .string): return .stringLowerParameter case .associatedValueEnum(let fullName): let base = fullName.components(separatedBy: ".").last ?? fullName return .associatedEnumLowerParameter(enumBase: base) @@ -1384,31 +1339,24 @@ struct IntrinsicJSFragment: Sendable { return try arrayLower(elementType: elementType) case .dictionary(let valueType): return try dictionaryLower(valueType: valueType) + default: + throw BridgeJSLinkError(message: "Unhandled type in lowerParameter: \(type)") } } /// Returns a fragment that lifts a Wasm core value to a JS value for return values static func liftReturn(type: BridgeType) throws -> IntrinsicJSFragment { + if let scalar = scalarFragments(for: type) { return scalar.lift } switch type { - case .int, .float, .double: return .identity - case .uint: return .uintLiftReturn - case .bool: return .boolLiftReturn case .string: return .stringLiftReturn case .jsObject: return .jsObjectLiftReturn case .jsValue: return .jsValueLift case .swiftHeapObject(let name): return .swiftHeapObjectLiftReturn(name) - case .unsafePointer: return .identity case .swiftProtocol: return .jsObjectLiftReturn case .void: return .void case .nullable(let wrappedType, let kind): return .optionalLiftReturn(wrappedType: wrappedType, kind: kind) - case .caseEnum: return .identity - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: return .stringLiftReturn - case .bool: return .boolLiftReturn - default: return .identity - } + case .rawValueEnum(_, .string): return .stringLiftReturn case .associatedValueEnum(let fullName): let base = fullName.components(separatedBy: ".").last ?? fullName return .associatedEnumLiftReturn(enumBase: base) @@ -1431,6 +1379,8 @@ struct IntrinsicJSFragment: Sendable { return try arrayLift(elementType: elementType) case .dictionary(let valueType): return try dictionaryLift(valueType: valueType) + default: + throw BridgeJSLinkError(message: "Unhandled type in liftReturn: \(type)") } } @@ -1438,14 +1388,11 @@ struct IntrinsicJSFragment: Sendable { /// Returns a fragment that lifts Wasm core values to JS values for parameters static func liftParameter(type: BridgeType, context: BridgeContext = .importTS) throws -> IntrinsicJSFragment { + if let scalar = scalarFragments(for: type) { return scalar.lift } switch type { - case .int, .float, .double: return .identity - case .uint: return .uintLiftParameter - case .bool: return .boolLiftParameter case .string: return .stringLiftParameter case .jsObject: return .jsObjectLiftParameter case .jsValue: return .jsValueLiftParameter - case .unsafePointer: return .identity case .swiftHeapObject(let name): return .swiftHeapObjectLiftParameter(name) case .swiftProtocol: return .jsObjectLiftParameter @@ -1454,14 +1401,8 @@ struct IntrinsicJSFragment: Sendable { message: "Void can't appear in parameters of imported JS functions" ) case .nullable(let wrappedType, let kind): - return try .optionalLiftParameter(wrappedType: wrappedType, kind: kind) - case .caseEnum: return .identity - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: return .stringLiftParameter - case .bool: return .boolLiftParameter - default: return .identity - } + return try .optionalLiftParameter(wrappedType: wrappedType, kind: kind, context: context) + case .rawValueEnum(_, .string): return .stringLiftParameter case .associatedValueEnum(let fullName): switch context { case .importTS: @@ -1519,31 +1460,24 @@ struct IntrinsicJSFragment: Sendable { return try arrayLift(elementType: elementType) case .dictionary(let valueType): return try dictionaryLift(valueType: valueType) + default: + throw BridgeJSLinkError(message: "Unhandled type in liftParameter: \(type)") } } /// Returns a fragment that lowers a JS value to Wasm core values for return values static func lowerReturn(type: BridgeType, context: BridgeContext = .importTS) throws -> IntrinsicJSFragment { + if let scalar = scalarFragments(for: type) { return scalar.lower } switch type { - case .int, .uint, .float, .double: return .identity - case .bool: return .boolLowerReturn case .string: return .stringLowerReturn case .jsObject: return .jsObjectLowerReturn case .jsValue: return .jsValueLowerReturn(context: context) - case .unsafePointer: return .identity - case .swiftHeapObject: - return .swiftHeapObjectLowerReturn + case .swiftHeapObject: return .swiftHeapObjectLowerReturn case .swiftProtocol: return .jsObjectLowerReturn case .void: return .void case .nullable(let wrappedType, let kind): return try .optionalLowerReturn(wrappedType: wrappedType, kind: kind) - case .caseEnum: return .identity - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: return .stringLowerReturn - case .bool: return .boolLowerReturn - default: return .identity - } + case .rawValueEnum(_, .string): return .stringLowerReturn case .associatedValueEnum(let fullName): switch context { case .importTS: @@ -1557,7 +1491,6 @@ struct IntrinsicJSFragment: Sendable { case .swiftStruct(let fullName): switch context { case .importTS: - // ImportTS expects Swift structs to come back as a retained JS object ID. return .jsObjectLowerReturn case .exportSwift: return swiftStructLowerReturn(fullName: fullName) @@ -1584,6 +1517,8 @@ struct IntrinsicJSFragment: Sendable { return try arrayLower(elementType: elementType) case .dictionary(let valueType): return try dictionaryLower(valueType: valueType) + default: + throw BridgeJSLinkError(message: "Unhandled type in lowerReturn: \(type)") } } @@ -1594,14 +1529,12 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let (scope, printer) = (context.scope, context.printer) let value = arguments[0] let caseIdVar = scope.variable("caseId") - let cleanupVar = scope.variable("cleanup") printer.write( - "const { caseId: \(caseIdVar), cleanup: \(cleanupVar) } = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(value));" + "const \(caseIdVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(value));" ) - cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") printer.write("return \(caseIdVar);") return [] } @@ -1645,14 +1578,9 @@ struct IntrinsicJSFragment: Sendable { let (scope, printer) = (context.scope, context.printer) let enumName = arguments[0] - printer.write("const __bjs_create\(enumName)Helpers = () => {") - printer.indent() - printer.write( - "return () => ({" - ) + printer.write("const __bjs_create\(enumName)Helpers = () => ({") printer.indent() - // Generate lower function printer.write("lower: (value) => {") try printer.indent { printer.write("const enumTag = value.tag;") @@ -1662,15 +1590,10 @@ struct IntrinsicJSFragment: Sendable { for enumCase in enumDefinition.cases { let caseName = enumCase.name.capitalizedFirstLetter let caseScope = scope.makeChildScope() - let caseCleanup = CodeFragmentPrinter() - caseCleanup.indent() let fragment = IntrinsicJSFragment.associatedValuePushPayload(enumCase: enumCase) _ = try fragment.printCode( ["value", enumName, caseName], - context.with(\.scope, caseScope).with(\.printer, lowerPrinter).with( - \.cleanupCode, - caseCleanup - ) + context.with(\.scope, caseScope).with(\.printer, lowerPrinter) ) } @@ -1696,15 +1619,11 @@ struct IntrinsicJSFragment: Sendable { for enumCase in enumDefinition.cases { let caseName = enumCase.name.capitalizedFirstLetter let caseScope = scope.makeChildScope() - let caseCleanup = CodeFragmentPrinter() let fragment = IntrinsicJSFragment.associatedValuePopPayload(enumCase: enumCase) _ = try fragment.printCode( [enumName, caseName], - context.with(\.scope, caseScope).with(\.printer, liftPrinter).with( - \.cleanupCode, - caseCleanup - ) + context.with(\.scope, caseScope).with(\.printer, liftPrinter) ) } @@ -1721,40 +1640,13 @@ struct IntrinsicJSFragment: Sendable { printer.write("}") printer.unindent() printer.write("});") - printer.unindent() - printer.write("};") - - return [] - } - ) - } - - static func simpleEnumHelper(enumDefinition: ExportedEnum) -> IntrinsicJSFragment { - return IntrinsicJSFragment( - parameters: ["enumName"], - printCode: { arguments, context in - let printer = context.printer - let enumName = arguments[0] - printer.write("const \(enumName) = {") - printer.indent { - for (index, enumCase) in enumDefinition.cases.enumerated() { - let caseName = enumCase.name.capitalizedFirstLetter - let value = enumCase.jsValue( - rawType: enumDefinition.rawType, - index: index - ) - printer.write("\(caseName): \(value),") - } - } - printer.write("};") - printer.nextLine() return [] } ) } - static func rawValueEnumHelper(enumDefinition: ExportedEnum) -> IntrinsicJSFragment { + static func caseEnumHelper(enumDefinition: ExportedEnum) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["enumName"], printCode: { arguments, context in @@ -1783,7 +1675,7 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["value", "enumName", "caseName"], printCode: { arguments, context in - let (printer, cleanup) = (context.printer, context.cleanupCode) + let printer = context.printer let enumName = arguments[1] let caseName = arguments[2] @@ -1791,10 +1683,8 @@ struct IntrinsicJSFragment: Sendable { try printer.indent { if enumCase.associatedValues.isEmpty { - printer.write("const cleanup = undefined;") - printer.write("return { caseId: \(enumName).Tag.\(caseName), cleanup };") + printer.write("return \(enumName).Tag.\(caseName);") } else { - // Process associated values in reverse order (to match the order they'll be popped) let reversedValues = enumCase.associatedValues.enumerated().reversed() for (associatedValueIndex, associatedValue) in reversedValues { @@ -1806,14 +1696,7 @@ struct IntrinsicJSFragment: Sendable { _ = try fragment.printCode(["value.\(prop)"], context) } - if cleanup.lines.isEmpty { - printer.write("const cleanup = undefined;") - } else { - printer.write("const cleanup = () => {") - printer.write(contentsOf: cleanup) - printer.write("};") - } - printer.write("return { caseId: \(enumName).Tag.\(caseName), cleanup };") + printer.write("return \(enumName).Tag.\(caseName);") } } @@ -1869,7 +1752,7 @@ struct IntrinsicJSFragment: Sendable { private static func associatedValuePushPayload(type: BridgeType) throws -> IntrinsicJSFragment { switch type { case .nullable(let wrappedType, let kind): - return associatedValueOptionalPushPayload(wrappedType: wrappedType, kind: kind) + return try associatedValueOptionalPushPayload(wrappedType: wrappedType, kind: kind) default: return try stackLowerFragment(elementType: type) } @@ -1878,183 +1761,43 @@ struct IntrinsicJSFragment: Sendable { private static func associatedValueOptionalPushPayload( wrappedType: BridgeType, kind: JSOptionalKind - ) -> IntrinsicJSFragment { - return IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) - let value = arguments[0] - let isSomeVar = scope.variable("isSome") - printer.write("const \(isSomeVar) = \(kind.presenceCheck(value: value));") - - switch wrappedType { - case .string: - let idVar = scope.variable("id") - printer.write("let \(idVar);") - printer.write("if (\(isSomeVar)) {") - printer.indent { - let bytesVar = scope.variable("bytes") - printer.write( - "let \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));" - ) - printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));") - scope.emitPushI32Parameter("\(bytesVar).length", printer: printer) - scope.emitPushI32Parameter(idVar, printer: printer) - } - printer.write("} else {") - printer.indent { - scope.emitPushI32Parameter("0", printer: printer) - scope.emitPushI32Parameter("0", printer: printer) - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - case .int, .uint: - scope.emitPushI32Parameter("\(isSomeVar) ? (\(value) | 0) : 0", printer: printer) - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - case .bool: - scope.emitPushI32Parameter("\(isSomeVar) ? (\(value) ? 1 : 0) : 0", printer: printer) - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - case .float: - scope.emitPushF32Parameter("\(isSomeVar) ? Math.fround(\(value)) : 0.0", printer: printer) - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - case .double: - scope.emitPushF64Parameter("\(isSomeVar) ? \(value) : 0.0", printer: printer) - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - case .caseEnum: - scope.emitPushI32Parameter("\(isSomeVar) ? (\(value) | 0) : 0", printer: printer) - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - let idVar = scope.variable("id") - printer.write("let \(idVar);") - printer.write("if (\(isSomeVar)) {") - printer.indent { - let bytesVar = scope.variable("bytes") - printer.write( - "let \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));" - ) - printer.write( - "\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));" - ) - scope.emitPushI32Parameter("\(bytesVar).length", printer: printer) - scope.emitPushI32Parameter(idVar, printer: printer) - } - printer.write("} else {") - printer.indent { - scope.emitPushI32Parameter("0", printer: printer) - scope.emitPushI32Parameter("0", printer: printer) - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - case .float: - scope.emitPushF32Parameter("\(isSomeVar) ? Math.fround(\(value)) : 0.0", printer: printer) - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - case .double: - scope.emitPushF64Parameter("\(isSomeVar) ? \(value) : 0.0", printer: printer) - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - default: - scope.emitPushI32Parameter("\(isSomeVar) ? (\(value) | 0) : 0", printer: printer) - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - } - case .swiftStruct(let structName): - let structBase = structName.components(separatedBy: ".").last ?? structName - let nestedCleanupVar = scope.variable("nestedCleanup") - printer.write("let \(nestedCleanupVar);") - printer.write("if (\(isSomeVar)) {") - printer.indent { - let structResultVar = scope.variable("structResult") - printer.write( - "const \(structResultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(structBase).lower(\(value));" - ) - printer.write("\(nestedCleanupVar) = \(structResultVar).cleanup;") - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - cleanup.write("if (\(nestedCleanupVar)) { \(nestedCleanupVar)(); }") - case .swiftHeapObject: - printer.write("if (\(isSomeVar)) {") - printer.indent { - scope.emitPushPointerParameter("\(value).pointer", printer: printer) - } - printer.write("} else {") - printer.indent { - scope.emitPushPointerParameter("0", printer: printer) - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - case .jsObject: - let idVar = scope.variable("id") - printer.write("let \(idVar);") - printer.write("if (\(isSomeVar)) {") - printer.indent { - printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") - scope.emitPushI32Parameter(idVar, printer: printer) - } - printer.write("} else {") - printer.indent { - printer.write("\(idVar) = undefined;") - scope.emitPushI32Parameter("0", printer: printer) - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - case .associatedValueEnum(let enumName): - let base = enumName.components(separatedBy: ".").last ?? enumName - let caseIdVar = scope.variable("enumCaseId") - let enumCleanupVar = scope.variable("enumCleanup") - printer.write("let \(caseIdVar), \(enumCleanupVar);") - printer.write("if (\(isSomeVar)) {") - printer.indent { - let enumResultVar = scope.variable("enumResult") - printer.write( - "const \(enumResultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(value));" - ) - printer.write("\(caseIdVar) = \(enumResultVar).caseId;") - printer.write("\(enumCleanupVar) = \(enumResultVar).cleanup;") - scope.emitPushI32Parameter(caseIdVar, printer: printer) - } - printer.write("} else {") - printer.indent { - scope.emitPushI32Parameter("0", printer: printer) - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - cleanup.write("if (\(enumCleanupVar)) { \(enumCleanupVar)(); }") - case .array(let elementType): - // Array cleanup references variables declared inside the if block, - // so capture cleanup into a variable declared at the outer scope. - let arrCleanupVar = scope.variable("arrCleanup") - printer.write("let \(arrCleanupVar);") - printer.write("if (\(isSomeVar)) {") - try printer.indent { - let localCleanup = CodeFragmentPrinter() - let arrFragment = try arrayLower(elementType: elementType) - _ = try arrFragment.printCode( - [value], - context.with(\.cleanupCode, localCleanup) - ) - let cleanupLines = localCleanup.lines.filter { - !$0.trimmingCharacters(in: .whitespaces).isEmpty - } - if !cleanupLines.isEmpty { - printer.write("\(arrCleanupVar) = () => {") - printer.indent { - for line in cleanupLines { - printer.write(line) - } - } - printer.write("};") + ) throws -> IntrinsicJSFragment { + let desc = wrappedType.descriptor + if let glue = desc.jsCoercion, desc.wasmParams.count == 1 { + let wasmType = desc.wasmParams[0].type + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let value = arguments[0] + let isSomeVar = scope.variable("isSome") + printer.write("const \(isSomeVar) = \(kind.presenceCheck(value: value));") + var coerced: String + if let coerce = glue.effectiveStackLowerCoerce { + coerced = coerce.replacingOccurrences(of: "$0", with: value) + if coerced.contains("?") && !coerced.hasPrefix("(") { + coerced = "(\(coerced))" } + } else { + coerced = value } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - cleanup.write("if (\(arrCleanupVar)) { \(arrCleanupVar)(); }") - default: + emitPush( + for: wasmType, + value: "\(isSomeVar) ? \(coerced) : \(wasmType.jsZeroLiteral)", + scope: scope, + printer: printer + ) scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + return [] } + ) + } - return [] - } + let innerFragment = try stackLowerFragment(elementType: wrappedType) + return stackOptionalLower( + wrappedType: wrappedType, + kind: kind, + innerFragment: innerFragment ) } @@ -2112,37 +1855,26 @@ struct IntrinsicJSFragment: Sendable { ) } - static func swiftStructLowerReturn(fullName: String) -> IntrinsicJSFragment { - let base = fullName.components(separatedBy: ".").last ?? fullName - return IntrinsicJSFragment( + private static func swiftStructLower(structBase: String) -> IntrinsicJSFragment { + IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let printer = context.printer let value = arguments[0] - let cleanupVar = scope.variable("cleanup") printer.write( - "const { cleanup: \(cleanupVar) } = \(JSGlueVariableScope.reservedStructHelpers).\(base).lower(\(value));" + "\(JSGlueVariableScope.reservedStructHelpers).\(structBase).lower(\(value));" ) - cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") return [] } ) } + static func swiftStructLowerReturn(fullName: String) -> IntrinsicJSFragment { + swiftStructLower(structBase: fullName.components(separatedBy: ".").last ?? fullName) + } + static func swiftStructLowerParameter(structBase: String) -> IntrinsicJSFragment { - return IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) - let value = arguments[0] - let cleanupVar = scope.variable("cleanup") - printer.write( - "const { cleanup: \(cleanupVar) } = \(JSGlueVariableScope.reservedStructHelpers).\(structBase).lower(\(value));" - ) - cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") - return [] - } - ) + swiftStructLower(structBase: structBase) } static func swiftStructLiftReturn(structBase: String) -> IntrinsicJSFragment { @@ -2166,33 +1898,20 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["arr"], printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let (scope, printer) = (context.scope, context.printer) let arr = arguments[0] - let cleanupArrayVar = scope.variable("arrayCleanups") - printer.write("const \(cleanupArrayVar) = [];") let elemVar = scope.variable("elem") printer.write("for (const \(elemVar) of \(arr)) {") try printer.indent { let elementFragment = try stackLowerFragment(elementType: elementType) - let elementCleanup = CodeFragmentPrinter() let _ = try elementFragment.printCode( [elemVar], - context.with(\.cleanupCode, elementCleanup) + context ) - if !elementCleanup.lines.isEmpty { - printer.write("\(cleanupArrayVar).push(() => {") - printer.indent { - for line in elementCleanup.lines { - printer.write(line) - } - } - printer.write("});") - } } printer.write("}") scope.emitPushI32Parameter("\(arr).length", printer: printer) - cleanupCode.write("for (const cleanup of \(cleanupArrayVar)) { cleanup(); }") return [] } ) @@ -2203,11 +1922,9 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["dict"], printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let (scope, printer) = (context.scope, context.printer) let dict = arguments[0] - let cleanupArrayVar = scope.variable("arrayCleanups") - printer.write("const \(cleanupArrayVar) = [];") let entriesVar = scope.variable("entries") let entryVar = scope.variable("entry") printer.write("const \(entriesVar) = Object.entries(\(dict));") @@ -2218,40 +1935,19 @@ struct IntrinsicJSFragment: Sendable { printer.write("const [\(keyVar), \(valueVar)] = \(entryVar);") let keyFragment = try stackLowerFragment(elementType: .string) - let keyCleanup = CodeFragmentPrinter() let _ = try keyFragment.printCode( [keyVar], - context.with(\.cleanupCode, keyCleanup) + context ) - if !keyCleanup.lines.isEmpty { - printer.write("\(cleanupArrayVar).push(() => {") - printer.indent { - for line in keyCleanup.lines { - printer.write(line) - } - } - printer.write("});") - } let valueFragment = try stackLowerFragment(elementType: valueType) - let valueCleanup = CodeFragmentPrinter() let _ = try valueFragment.printCode( [valueVar], - context.with(\.cleanupCode, valueCleanup) + context ) - if !valueCleanup.lines.isEmpty { - printer.write("\(cleanupArrayVar).push(() => {") - printer.indent { - for line in valueCleanup.lines { - printer.write(line) - } - } - printer.write("});") - } } printer.write("}") scope.emitPushI32Parameter("\(entriesVar).length", printer: printer) - cleanupCode.write("for (const cleanup of \(cleanupArrayVar)) { cleanup(); }") return [] } ) @@ -2313,6 +2009,28 @@ struct IntrinsicJSFragment: Sendable { } private static func stackLiftFragment(elementType: BridgeType) throws -> IntrinsicJSFragment { + if case .nullable(let wrappedType, let kind) = elementType { + return try optionalElementRaiseFragment(wrappedType: wrappedType, kind: kind) + } + let desc = elementType.descriptor + if let glue = desc.jsCoercion, desc.wasmParams.count == 1 { + let wasmType = desc.wasmParams[0].type + return IntrinsicJSFragment( + parameters: [], + printCode: { _, context in + let (scope, printer) = (context.scope, context.printer) + let popExpr = popExpression(for: wasmType, scope: scope) + let varName = scope.variable(glue.varHint) + if let transform = glue.liftCoerce { + let inlined = transform.replacingOccurrences(of: "$0", with: popExpr) + printer.write("const \(varName) = \(inlined);") + } else { + printer.write("const \(varName) = \(popExpr);") + } + return [varName] + } + ) + } switch elementType { case .jsValue: return IntrinsicJSFragment( @@ -2343,44 +2061,14 @@ struct IntrinsicJSFragment: Sendable { return [strVar] } ) - case .bool: - return IntrinsicJSFragment( - parameters: [], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let bVar = scope.variable("bool") - printer.write("const \(bVar) = \(scope.popI32()) !== 0;") - return [bVar] - } - ) - case .int, .uint: - return IntrinsicJSFragment( - parameters: [], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let iVar = scope.variable("int") - printer.write("const \(iVar) = \(scope.popI32());") - return [iVar] - } - ) - case .float: - return IntrinsicJSFragment( - parameters: [], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let fVar = scope.variable("f32") - printer.write("const \(fVar) = \(scope.popF32());") - return [fVar] - } - ) - case .double: + case .rawValueEnum(_, .string): return IntrinsicJSFragment( parameters: [], printCode: { arguments, context in let (scope, printer) = (context.scope, context.printer) - let dVar = scope.variable("f64") - printer.write("const \(dVar) = \(scope.popF64());") - return [dVar] + let varName = scope.variable("rawValue") + printer.write("const \(varName) = \(scope.popString());") + return [varName] } ) case .swiftStruct(let fullName): @@ -2396,59 +2084,6 @@ struct IntrinsicJSFragment: Sendable { return [resultVar] } ) - case .caseEnum: - return IntrinsicJSFragment( - parameters: [], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let varName = scope.variable("caseId") - printer.write("const \(varName) = \(scope.popI32());") - return [varName] - } - ) - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - return IntrinsicJSFragment( - parameters: [], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let varName = scope.variable("rawValue") - printer.write("const \(varName) = \(scope.popString());") - return [varName] - } - ) - case .float: - return IntrinsicJSFragment( - parameters: [], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let varName = scope.variable("rawValue") - printer.write("const \(varName) = \(scope.popF32());") - return [varName] - } - ) - case .double: - return IntrinsicJSFragment( - parameters: [], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let varName = scope.variable("rawValue") - printer.write("const \(varName) = \(scope.popF64());") - return [varName] - } - ) - default: - return IntrinsicJSFragment( - parameters: [], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let varName = scope.variable("rawValue") - printer.write("const \(varName) = \(scope.popI32());") - return [varName] - } - ) - } case .associatedValueEnum(let fullName): let base = fullName.components(separatedBy: ".").last ?? fullName return IntrinsicJSFragment( @@ -2457,7 +2092,7 @@ struct IntrinsicJSFragment: Sendable { let (scope, printer) = (context.scope, context.printer) let resultVar = scope.variable("enumValue") printer.write( - "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(scope.popI32()), );" + "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(scope.popI32()));" ) return [resultVar] } @@ -2482,7 +2117,9 @@ struct IntrinsicJSFragment: Sendable { let idVar = scope.variable("objId") let objVar = scope.variable("obj") printer.write("const \(idVar) = \(scope.popI32());") - printer.write("const \(objVar) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(idVar));") + printer.write( + "const \(objVar) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(idVar));" + ) printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(idVar));") return [objVar] } @@ -2491,24 +2128,34 @@ struct IntrinsicJSFragment: Sendable { return try arrayLift(elementType: innerElementType) case .dictionary(let valueType): return try dictionaryLift(valueType: valueType) - case .nullable(let wrappedType, let kind): - return try optionalElementRaiseFragment(wrappedType: wrappedType, kind: kind) - case .unsafePointer: + default: + throw BridgeJSLinkError(message: "Unsupported array element type: \(elementType)") + } + } + + private static func stackLowerFragment(elementType: BridgeType) throws -> IntrinsicJSFragment { + if case .nullable(let wrappedType, let kind) = elementType { + return try optionalElementLowerFragment(wrappedType: wrappedType, kind: kind) + } + let desc = elementType.descriptor + if let glue = desc.jsCoercion, desc.wasmParams.count == 1 { + let wasmType = desc.wasmParams[0].type return IntrinsicJSFragment( - parameters: [], + parameters: ["value"], printCode: { arguments, context in let (scope, printer) = (context.scope, context.printer) - let pVar = scope.variable("pointer") - printer.write("const \(pVar) = \(scope.popPointer());") - return [pVar] + let value = arguments[0] + let pushExpr: String + if let coerce = glue.effectiveStackLowerCoerce { + pushExpr = coerce.replacingOccurrences(of: "$0", with: value) + } else { + pushExpr = value + } + emitPush(for: wasmType, value: pushExpr, scope: scope, printer: printer) + return [] } ) - case .void, .closure, .namespaceEnum: - throw BridgeJSLinkError(message: "Unsupported array element type: \(elementType)") } - } - - private static func stackLowerFragment(elementType: BridgeType) throws -> IntrinsicJSFragment { switch elementType { case .jsValue: return IntrinsicJSFragment( @@ -2526,7 +2173,7 @@ struct IntrinsicJSFragment: Sendable { return [] } ) - case .string: + case .string, .rawValueEnum(_, .string): return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in @@ -2534,136 +2181,43 @@ struct IntrinsicJSFragment: Sendable { let value = arguments[0] let bytesVar = scope.variable("bytes") let idVar = scope.variable("id") - printer.write("const \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));") - printer.write("const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));") + printer.write( + "const \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));" + ) + printer.write( + "const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));" + ) scope.emitPushI32Parameter("\(bytesVar).length", printer: printer) scope.emitPushI32Parameter(idVar, printer: printer) return [] } ) - case .bool: - return IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - scope.emitPushI32Parameter("\(arguments[0]) ? 1 : 0", printer: printer) - return [] - } - ) - case .int, .uint: - return IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - scope.emitPushI32Parameter("(\(arguments[0]) | 0)", printer: printer) - return [] - } - ) - case .float: - return IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - scope.emitPushF32Parameter("Math.fround(\(arguments[0]))", printer: printer) - return [] - } - ) - case .double: - return IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - scope.emitPushF64Parameter("\(arguments[0])", printer: printer) - return [] - } - ) case .swiftStruct(let fullName): let structBase = fullName.components(separatedBy: ".").last ?? fullName return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in - let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) + let printer = context.printer let value = arguments[0] - let cleanupVar = scope.variable("structCleanup") printer.write( - "const { cleanup: \(cleanupVar) } = \(JSGlueVariableScope.reservedStructHelpers).\(structBase).lower(\(value));" + "\(JSGlueVariableScope.reservedStructHelpers).\(structBase).lower(\(value));" ) - cleanup.write("if (\(cleanupVar)) { \(cleanupVar)(); }") - return [] - } - ) - case .caseEnum: - return IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - scope.emitPushI32Parameter("(\(arguments[0]) | 0)", printer: printer) return [] } ) - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - return IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let value = arguments[0] - let bytesVar = scope.variable("bytes") - let idVar = scope.variable("id") - printer.write( - "const \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));" - ) - printer.write( - "const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));" - ) - scope.emitPushI32Parameter("\(bytesVar).length", printer: printer) - scope.emitPushI32Parameter(idVar, printer: printer) - return [] - } - ) - case .float: - return IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - scope.emitPushF32Parameter("Math.fround(\(arguments[0]))", printer: printer) - return [] - } - ) - case .double: - return IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - scope.emitPushF64Parameter("\(arguments[0])", printer: printer) - return [] - } - ) - default: - return IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - scope.emitPushI32Parameter("(\(arguments[0]) | 0)", printer: printer) - return [] - } - ) - } + case .associatedValueEnum(let fullName): let base = fullName.components(separatedBy: ".").last ?? fullName return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in - let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) + let (scope, printer) = (context.scope, context.printer) let value = arguments[0] let caseIdVar = scope.variable("caseId") - let cleanupVar = scope.variable("enumCleanup") printer.write( - "const { caseId: \(caseIdVar), cleanup: \(cleanupVar) } = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(value));" + "const \(caseIdVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(value));" ) scope.emitPushI32Parameter(caseIdVar, printer: printer) - cleanup.write("if (\(cleanupVar)) { \(cleanupVar)(); }") return [] } ) @@ -2672,18 +2226,21 @@ struct IntrinsicJSFragment: Sendable { parameters: ["value"], printCode: { arguments, context in let (scope, printer) = (context.scope, context.printer) - scope.emitPushPointerParameter("\(arguments[0]).pointer", printer: printer) + let value = arguments[0] + scope.emitPushPointerParameter("\(value).pointer", printer: printer) return [] } ) - case .jsObject: + case .jsObject, .swiftProtocol: return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in let (scope, printer) = (context.scope, context.printer) let value = arguments[0] let idVar = scope.variable("objId") - printer.write("const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + printer.write( + "const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));" + ) scope.emitPushI32Parameter(idVar, printer: printer) return [] } @@ -2692,34 +2249,7 @@ struct IntrinsicJSFragment: Sendable { return try arrayLower(elementType: innerElementType) case .dictionary(let valueType): return try dictionaryLower(valueType: valueType) - case .nullable(let wrappedType, let kind): - return try optionalElementLowerFragment( - wrappedType: wrappedType, - kind: kind - ) - case .swiftProtocol: - // Same as jsObject but no cleanup — Swift's AnyProtocol wrapper releases via deinit - return IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let value = arguments[0] - let idVar = scope.variable("objId") - printer.write("const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") - scope.emitPushI32Parameter(idVar, printer: printer) - return [] - } - ) - case .unsafePointer: - return IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - scope.emitPushPointerParameter("(\(arguments[0]) | 0)", printer: printer) - return [] - } - ) - case .void, .closure, .namespaceEnum: + default: throw BridgeJSLinkError(message: "Unsupported array element type for lowering: \(elementType)") } } @@ -2772,44 +2302,31 @@ struct IntrinsicJSFragment: Sendable { let presenceExpr = kind.presenceCheck(value: value) printer.write("const \(isSomeVar) = \(presenceExpr) ? 1 : 0;") - // Cleanup is written inside the if block so retained id is in scope - let localCleanupWriter = CodeFragmentPrinter() printer.write("if (\(isSomeVar)) {") try printer.indent { let innerFragment = try stackLowerFragment(elementType: wrappedType) let _ = try innerFragment.printCode( [value], - context.with(\.cleanupCode, localCleanupWriter) + context ) - let localCleanupLines = localCleanupWriter.lines.filter { - !$0.trimmingCharacters(in: .whitespaces).isEmpty - } - if !localCleanupLines.isEmpty { - let localCleanupCode = localCleanupLines.joined(separator: " ") - printer.write("arrayCleanups.push(() => { \(localCleanupCode) });") - } } - printer.write("} else {") - printer.indent { - // Push placeholders so Swift can unconditionally pop value slots - switch wrappedType { - case .float: - scope.emitPushF32Parameter("0.0", printer: printer) - case .double: - scope.emitPushF64Parameter("0.0", printer: printer) - case .swiftStruct: - // No placeholder — Swift only pops struct fields when isSome=1 - break - case .string, .rawValueEnum(_, .string): - scope.emitPushI32Parameter("0", printer: printer) - scope.emitPushI32Parameter("0", printer: printer) - case .swiftHeapObject: - scope.emitPushPointerParameter("0", printer: printer) - default: - scope.emitPushI32Parameter("0", printer: printer) + let placeholderPrinter = CodeFragmentPrinter() + let hasPlaceholders = emitOptionalPlaceholders( + for: wrappedType, + scope: scope, + printer: placeholderPrinter + ) + if hasPlaceholders { + printer.write("} else {") + printer.indent { + for line in placeholderPrinter.lines { + printer.write(line) + } } + printer.write("}") + } else { + printer.write("}") } - printer.write("}") scope.emitPushI32Parameter(isSomeVar, printer: printer) return [] @@ -2817,6 +2334,8 @@ struct IntrinsicJSFragment: Sendable { ) } + // MARK: - Struct Helpers + static func structHelper(structDefinition: ExportedStruct, allStructs: [ExportedStruct]) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["structName"], @@ -2826,11 +2345,7 @@ struct IntrinsicJSFragment: Sendable { let capturedStructDef = structDefinition let capturedAllStructs = allStructs - printer.write("const __bjs_create\(structName)Helpers = () => {") - printer.indent() - printer.write( - "return () => ({" - ) + printer.write("const __bjs_create\(structName)Helpers = () => ({") printer.indent() printer.write("lower: (value) => {") @@ -2857,18 +2372,12 @@ struct IntrinsicJSFragment: Sendable { printer.write("}") printer.unindent() printer.write("});") - printer.unindent() - printer.write("};") return [] } ) } - private static func findStruct(name: String, structs: [ExportedStruct]) -> ExportedStruct? { - return structs.first(where: { $0.swiftCallName == name || $0.name == name }) - } - private static func generateStructLowerCode( structDef: ExportedStruct, allStructs: [ExportedStruct], @@ -2877,31 +2386,24 @@ struct IntrinsicJSFragment: Sendable { let (scope, printer) = (context.scope, context.printer) let lowerPrinter = CodeFragmentPrinter() let lowerScope = scope.makeChildScope() - let lowerCleanup = CodeFragmentPrinter() - lowerCleanup.indent() let instanceProps = structDef.properties.filter { !$0.isStatic } for property in instanceProps { - let fragment = try structFieldLowerFragment(field: property, allStructs: allStructs) + let fragment = try structFieldLowerFragment( + type: property.type, + fieldName: property.name, + allStructs: allStructs + ) let fieldValue = "value.\(property.name)" _ = try fragment.printCode( [fieldValue], - context.with(\.scope, lowerScope).with(\.printer, lowerPrinter).with(\.cleanupCode, lowerCleanup) + context.with(\.scope, lowerScope).with(\.printer, lowerPrinter) ) } for line in lowerPrinter.lines { printer.write(line) } - - if !lowerCleanup.lines.isEmpty { - printer.write("const cleanup = () => {") - printer.write(contentsOf: lowerCleanup) - printer.write("};") - printer.write("return { cleanup };") - } else { - printer.write("return { cleanup: undefined };") - } } private static func generateStructLiftCode( @@ -2910,7 +2412,7 @@ struct IntrinsicJSFragment: Sendable { context: IntrinsicJSFragment.PrintCodeContext, attachMethods: Bool = false ) throws { - let (scope, printer) = (context.scope, context.printer) + let printer = context.printer let liftScope = context.scope.makeChildScope() var fieldExpressions: [(name: String, expression: String)] = [] @@ -2944,12 +2446,8 @@ struct IntrinsicJSFragment: Sendable { "\(instanceVar).\(method.name) = function(\(paramList)) {" ) try printer.indent { - let methodScope = scope.makeChildScope() - let methodCleanup = CodeFragmentPrinter() - - let structCleanupVar = methodScope.variable("structCleanup") printer.write( - "const { cleanup: \(structCleanupVar) } = \(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lower(this);" + "\(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lower(this);" ) var paramForwardings: [String] = [] @@ -2966,10 +2464,6 @@ struct IntrinsicJSFragment: Sendable { printer.write("const ret = \(callExpr);") } - // Cleanup - printer.write("if (\(structCleanupVar)) { \(structCleanupVar)(); }") - printer.write(contentsOf: methodCleanup) - // Lift return value if needed if method.returnType != .void { let liftFragment = try IntrinsicJSFragment.liftReturn(type: method.returnType) @@ -2990,10 +2484,11 @@ struct IntrinsicJSFragment: Sendable { } private static func structFieldLowerFragment( - field: ExportedProperty, + type: BridgeType, + fieldName: String, allStructs: [ExportedStruct] ) throws -> IntrinsicJSFragment { - switch field.type { + switch type { case .jsValue: preconditionFailure("Struct field of JSValue is not supported yet") case .jsObject: @@ -3006,7 +2501,9 @@ struct IntrinsicJSFragment: Sendable { printer.write("let \(idVar);") printer.write("if (\(value) != null) {") printer.indent { - printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + printer.write( + "\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));" + ) } printer.write("} else {") printer.indent { @@ -3018,281 +2515,56 @@ struct IntrinsicJSFragment: Sendable { } ) case .nullable(let wrappedType, let kind): - return IntrinsicJSFragment( - parameters: ["value"], - printCode: { arguments, context in - let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) - let value = arguments[0] - let isSomeVar = scope.variable("isSome") - printer.write("const \(isSomeVar) = \(kind.presenceCheck(value: value));") - - if case .caseEnum = wrappedType { - printer.write("if (\(isSomeVar)) {") - printer.indent { - scope.emitPushI32Parameter("\(value) | 0", printer: printer) - } - printer.write("} else {") - printer.indent { - scope.emitPushI32Parameter("0", printer: printer) - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - return [] - } else if case .rawValueEnum(_, let rawType) = wrappedType { - switch rawType { - case .string: - let idVar = scope.variable("id") - printer.write("let \(idVar);") - printer.write("if (\(isSomeVar)) {") - printer.indent { - let bytesVar = scope.variable("bytes") - printer.write( - "const \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));" - ) - printer.write( - "\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));" - ) - scope.emitPushI32Parameter("\(bytesVar).length", printer: printer) - scope.emitPushI32Parameter(idVar, printer: printer) - } - printer.write("} else {") - printer.indent { - scope.emitPushI32Parameter("0", printer: printer) - scope.emitPushI32Parameter("0", printer: printer) - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - return [idVar] - case .float: - printer.write("if (\(isSomeVar)) {") - printer.indent { - scope.emitPushF32Parameter("Math.fround(\(value))", printer: printer) - } - printer.write("} else {") - printer.indent { - scope.emitPushF32Parameter("0.0", printer: printer) - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - return [] - case .double: - printer.write("if (\(isSomeVar)) {") - printer.indent { - scope.emitPushF64Parameter("\(value)", printer: printer) - } - printer.write("} else {") - printer.indent { - scope.emitPushF64Parameter("0.0", printer: printer) - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - return [] - default: - printer.write("if (\(isSomeVar)) {") - printer.indent { - scope.emitPushI32Parameter("\(value) | 0", printer: printer) - } - printer.write("} else {") - printer.indent { - scope.emitPushI32Parameter("0", printer: printer) - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - return [] - } - } else if case .swiftHeapObject = wrappedType { - let ptrVar = scope.variable("ptr") - printer.write("let \(ptrVar);") - printer.write("if (\(isSomeVar)) {") - printer.indent { - printer.write("\(ptrVar) = \(value).pointer;") - scope.emitPushPointerParameter("\(ptrVar)", printer: printer) - } - printer.write("} else {") - printer.indent { - scope.emitPushPointerParameter("0", printer: printer) - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - return [] - } else if case .swiftStruct(let structName) = wrappedType { - let nestedCleanupVar = scope.variable("nestedCleanup") - printer.write("let \(nestedCleanupVar);") - printer.write("if (\(isSomeVar)) {") - printer.indent { - let structResultVar = scope.variable("structResult") - printer.write( - "const \(structResultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(structName).lower(\(value));" - ) - printer.write("\(nestedCleanupVar) = \(structResultVar).cleanup;") - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - cleanup.write("if (\(nestedCleanupVar)) { \(nestedCleanupVar)(); }") - return [] - } else if case .string = wrappedType { - let idVar = scope.variable("id") - printer.write("let \(idVar);") - printer.write("if (\(isSomeVar)) {") - printer.indent { - let bytesVar = scope.variable("bytes") - printer.write( - "const \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));" - ) - printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));") - scope.emitPushI32Parameter("\(bytesVar).length", printer: printer) - scope.emitPushI32Parameter(idVar, printer: printer) - } - printer.write("} else {") - printer.indent { - scope.emitPushI32Parameter("0", printer: printer) - scope.emitPushI32Parameter("0", printer: printer) + let wrappedDesc = wrappedType.descriptor + if let glue = wrappedDesc.jsCoercion, wrappedDesc.wasmParams.count == 1 { + let wasmType = wrappedDesc.wasmParams[0].type + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let value = arguments[0] + let isSomeVar = scope.variable("isSome") + printer.write("const \(isSomeVar) = \(kind.presenceCheck(value: value));") + let coerced: String + if let coerce = glue.effectiveStackLowerCoerce { + coerced = coerce.replacingOccurrences(of: "$0", with: value) + } else { + coerced = value } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - return [idVar] - } else if case .jsObject = wrappedType { - let idVar = scope.variable("id") - printer.write("let \(idVar);") printer.write("if (\(isSomeVar)) {") printer.indent { - printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") - scope.emitPushI32Parameter(idVar, printer: printer) + emitPush(for: wasmType, value: coerced, scope: scope, printer: printer) } printer.write("} else {") printer.indent { - printer.write("\(idVar) = undefined;") - scope.emitPushI32Parameter("0", printer: printer) + emitPush(for: wasmType, value: wasmType.jsZeroLiteral, scope: scope, printer: printer) } printer.write("}") scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - return [idVar] - } else { - switch wrappedType { - case .int, .uint: - pushOptionalPrimitive( - value: value, - isSomeVar: isSomeVar, - stack: .i32Stack, - convert: "| 0", - zeroValue: "0", - printer: printer, - scope: scope - ) - case .bool: - pushOptionalPrimitive( - value: value, - isSomeVar: isSomeVar, - stack: .i32Stack, - convert: "? 1 : 0", - zeroValue: "0", - printer: printer, - scope: scope - ) - case .float: - pushOptionalPrimitive( - value: value, - isSomeVar: isSomeVar, - stack: .f32Stack, - convert: "Math.fround", - zeroValue: "0.0", - printer: printer, - scope: scope - ) - case .double: - pushOptionalPrimitive( - value: value, - isSomeVar: isSomeVar, - stack: .f64Stack, - convert: nil, - zeroValue: "0.0", - printer: printer, - scope: scope - ) - case .associatedValueEnum(let enumName): - let base = enumName.components(separatedBy: ".").last ?? enumName - let caseIdVar = scope.variable("enumCaseId") - let enumCleanupVar = scope.variable("enumCleanup") - printer.write("let \(caseIdVar), \(enumCleanupVar);") - printer.write("if (\(isSomeVar)) {") - printer.indent { - let enumResultVar = scope.variable("enumResult") - printer.write( - "const \(enumResultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(value));" - ) - printer.write("\(caseIdVar) = \(enumResultVar).caseId;") - printer.write("\(enumCleanupVar) = \(enumResultVar).cleanup;") - scope.emitPushI32Parameter(caseIdVar, printer: printer) - } - printer.write("} else {") - printer.indent { - scope.emitPushI32Parameter("0", printer: printer) - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - cleanup.write("if (\(enumCleanupVar)) { \(enumCleanupVar)(); }") - default: - let wrappedFragment = try structFieldLowerFragment( - field: ExportedProperty( - name: field.name, - type: wrappedType, - isReadonly: true, - isStatic: false - ), - allStructs: allStructs - ) - let guardedPrinter = CodeFragmentPrinter() - let guardedCleanup = CodeFragmentPrinter() - _ = try wrappedFragment.printCode( - [value], - context.with(\.printer, guardedPrinter).with(\.cleanupCode, guardedCleanup) - ) - var loweredLines = guardedPrinter.lines - var hoistedCleanupVar: String? - if let first = loweredLines.first { - let trimmed = first.trimmingCharacters(in: .whitespaces) - if trimmed.hasPrefix("const "), - let namePart = trimmed.split(separator: " ").dropFirst().first, - trimmed.contains("= []") - { - hoistedCleanupVar = String(namePart) - loweredLines[0] = "\(hoistedCleanupVar!) = [];" - } - } - if let hoistedName = hoistedCleanupVar { - printer.write("let \(hoistedName);") - } - printer.write("if (\(isSomeVar)) {") - printer.indent { - for line in loweredLines { - printer.write(line) - } - if !guardedCleanup.lines.isEmpty { - cleanup.write("if (\(isSomeVar)) {") - cleanup.indent { - cleanup.write(contentsOf: guardedCleanup) - } - cleanup.write("}") - } - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - } return [] } - } + ) + } + + let innerFragment = try structFieldLowerFragment( + type: wrappedType, + fieldName: fieldName, + allStructs: allStructs + ) + return stackOptionalLower( + wrappedType: wrappedType, + kind: kind, + innerFragment: innerFragment ) case .swiftStruct(let nestedName): return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) + let printer = context.printer let value = arguments[0] - let structResultVar = scope.variable("structResult") printer.write( - "const \(structResultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(nestedName).lower(\(value));" + "\(JSGlueVariableScope.reservedStructHelpers).\(nestedName).lower(\(value));" ) - context.cleanupCode.write("if (\(structResultVar).cleanup) { \(structResultVar).cleanup(); }") return [] } ) @@ -3302,61 +2574,17 @@ struct IntrinsicJSFragment: Sendable { parameters: ["value"], printCode: { arguments, context in context.printer.write( - "throw new Error(\"Unsupported struct field type for lowering: \(field.type)\");" + "throw new Error(\"Unsupported struct field type for lowering: \(type)\");" ) return [] } ) default: - return try stackLowerFragment(elementType: field.type) + return try stackLowerFragment(elementType: type) } } /// Helper to push optional primitive values to stack-based parameters - private static func pushOptionalPrimitive( - value: String, - isSomeVar: String, - stack: StackType, - convert: String?, - zeroValue: String, - printer: CodeFragmentPrinter, - scope: JSGlueVariableScope - ) { - let stackName: String - switch stack { - case .i32Stack: stackName = JSGlueVariableScope.reservedI32Stack - case .f32Stack: stackName = JSGlueVariableScope.reservedF32Stack - case .f64Stack: stackName = JSGlueVariableScope.reservedF64Stack - } - - printer.write("if (\(isSomeVar)) {") - printer.indent { - let converted: String - if let convert = convert { - if convert.starts(with: "Math.") { - converted = "\(convert)(\(value))" - } else { - converted = "\(value) \(convert)" - } - } else { - converted = value - } - printer.write("\(stackName).push(\(converted));") - } - printer.write("} else {") - printer.indent { - printer.write("\(stackName).push(\(zeroValue));") - } - printer.write("}") - scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) - } - - private enum StackType { - case i32Stack - case f32Stack - case f64Stack - } - private static func structFieldLiftFragment( field: ExportedProperty, allStructs: [ExportedStruct] @@ -3381,7 +2609,7 @@ struct IntrinsicJSFragment: Sendable { let caseIdVar = scope.variable("enumCaseId") printer.write("const \(caseIdVar) = \(scope.popI32());") printer.write( - "\(optVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(caseIdVar), );" + "\(optVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(caseIdVar));" ) } else { let wrappedFragment = try structFieldLiftFragment( diff --git a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift index ba25b6ff9..f1f0d3040 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift @@ -148,6 +148,28 @@ public enum JSOptionalKind: String, Codable, Equatable, Hashable, Sendable { } } +public enum SwiftEnumRawType: String, CaseIterable, Codable, Sendable { + case string = "String" + case bool = "Bool" + case int = "Int" + case int32 = "Int32" + case int64 = "Int64" + case uint = "UInt" + case uint32 = "UInt32" + case uint64 = "UInt64" + case float = "Float" + case double = "Double" + + public init?(_ rawTypeString: String?) { + guard let rawTypeString = rawTypeString, + let match = Self.allCases.first(where: { $0.rawValue == rawTypeString }) + else { + return nil + } + self = match + } +} + public enum BridgeType: Codable, Equatable, Hashable, Sendable { case int, uint, float, double, string, bool, jsObject(String?), jsValue, swiftHeapObject(String), void case unsafePointer(UnsafePointerType) @@ -165,46 +187,25 @@ public enum BridgeType: Codable, Equatable, Hashable, Sendable { public enum WasmCoreType: String, Codable, Sendable { case i32, i64, f32, f64, pointer -} - -public enum SwiftEnumRawType: String, CaseIterable, Codable, Sendable { - case string = "String" - case bool = "Bool" - case int = "Int" - case int32 = "Int32" - case int64 = "Int64" - case uint = "UInt" - case uint32 = "UInt32" - case uint64 = "UInt64" - case float = "Float" - case double = "Double" - public var wasmCoreType: WasmCoreType? { + public var jsZeroLiteral: String { switch self { - case .string: - return nil - case .bool, .int, .int32, .uint, .uint32: - return .i32 - case .int64, .uint64: - return .i64 - case .float: - return .f32 - case .double: - return .f64 + case .f32, .f64: return "0.0" + case .i32, .i64, .pointer: return "0" } } - public init?(_ rawTypeString: String?) { - guard let rawTypeString = rawTypeString, - let match = Self.allCases.first(where: { $0.rawValue == rawTypeString }) - else { - return nil + 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" } - self = match } } -/// Represents a struct field with name and default value for default parameter values public struct DefaultValueField: Codable, Equatable, Sendable { public let name: String public let value: DefaultValue @@ -222,11 +223,11 @@ public enum DefaultValue: Codable, Equatable, Sendable { case double(Double) case bool(Bool) case null - case enumCase(String, String) // enumName, caseName - case object(String) // className for parameterless constructor - case objectWithArguments(String, [DefaultValue]) // className, constructor argument values - case structLiteral(String, [DefaultValueField]) // structName, field name/value pairs - indirect case array([DefaultValue]) // array literal with element values + case enumCase(String, String) + case object(String) + case objectWithArguments(String, [DefaultValue]) + case structLiteral(String, [DefaultValueField]) + indirect case array([DefaultValue]) } public struct Parameter: Codable, Equatable, Sendable { @@ -247,6 +248,510 @@ public struct Parameter: Codable, Equatable, Sendable { } } +public struct Effects: Codable, Equatable, Sendable { + public var isAsync: Bool + public var isThrows: Bool + public var isStatic: Bool + + public init(isAsync: Bool, isThrows: Bool, isStatic: Bool = false) { + self.isAsync = isAsync + self.isThrows = isThrows + self.isStatic = isStatic + } +} + +public enum StaticContext: Codable, Equatable, Sendable { + case className(String) + case structName(String) + case enumName(String) + case namespaceEnum(String) +} + +// MARK: - ABI Descriptor + +/// How `Optional` is represented at the WASM ABI boundary. +/// +/// The convention is derived from T's descriptor and determines how codegen +/// handles nullable values in both the parameter and return directions. +/// Stack ABI is the general-purpose fallback that works for any T. +public enum OptionalConvention: Sendable, Equatable { + /// Everything goes through the stack (isSome flag + payload pushed/popped). + /// Used for types whose base representation already uses the stack (struct, array, dictionary). + /// This is also the default fallback for unknown types. + case stackABI + + /// isSome is passed as an inline WASM parameter alongside T's normal parameters. + /// For returns, T's return type carries the value (no side channel needed). + /// Used for types with compact representations where the value space has no sentinel + /// (bool, jsValue, closure, caseEnum, associatedValueEnum). + case inlineFlag + + /// Return value goes through a side-channel storage variable; WASM function returns void. + /// For parameters, behaves like `.inlineFlag` (isSome + T's params as direct WASM params). + /// Used for scalar types where Optional return needs disambiguation (int, string, jsObject, etc.). + case sideChannelReturn(OptionalSideChannel) +} + +public enum OptionalSideChannel: Sendable, Equatable { + case none + case storage + case retainedObject +} + +/// A bit pattern that is never a valid value for a type, usable to represent `nil` +/// without an extra `isSome` flag. Inspired by Swift's "extra inhabitant" concept. +/// +/// Types with a nil sentinel can encode Optional in T's own return slot: +/// the sentinel value means absent, any other value means present. +/// Types without a sentinel need either an inline isSome flag or a side channel. +public enum NilSentinel: Sendable, Equatable { + /// No sentinel exists - all bit patterns are valid values. + case none + /// A specific i32 value is never valid (e.g. 0 for object IDs, -1 for enum tags). + case i32(Int32) + /// A null pointer (0) is the sentinel. + case pointer + + public var jsLiteral: String { + switch self { + case .none: fatalError("No sentinel value for .none") + case .i32(let value): return "\(value)" + case .pointer: return "0" + } + } + + public var hasSentinel: Bool { + self != .none + } +} + +/// Identifies which typed optional-return storage slot a scalar type uses. +/// +/// On the Swift -> JS path, Swift calls `swift_js_return_optional_(isSome, value)` +/// which writes to the corresponding `tmpRetOptional` variable in JS. +/// On the JS -> Swift path (protocol returns), the same storage and intrinsic are used +/// unless the type has a nil sentinel (in which case the sentinel path is taken instead). +public enum OptionalScalarKind: String, Sendable { + case bool, int, float, double + + public var storageName: String { "tmpRetOptional\(rawValue.prefix(1).uppercased())\(rawValue.dropFirst())" } + public var funcName: String { "swift_js_return_optional_\(rawValue)" } +} + +/// JS-side coercion info for simple single-value ABI types. +/// Coercion strings use `$0` as a placeholder for the value expression. +/// Grouped within the type descriptor to avoid duplicate per-BridgeType switching. +public struct JSCoercion: Sendable { + public let liftCoerce: String? + public let lowerCoerce: String? + public let stackLowerCoerce: String? + public let varHint: String + public let optionalScalarKind: OptionalScalarKind? + + public init( + liftCoerce: String? = nil, + lowerCoerce: String? = nil, + stackLowerCoerce: String? = nil, + varHint: String, + optionalScalarKind: OptionalScalarKind? = nil + ) { + self.liftCoerce = liftCoerce + self.lowerCoerce = lowerCoerce + self.stackLowerCoerce = stackLowerCoerce + self.varHint = varHint + self.optionalScalarKind = optionalScalarKind + } + + public var effectiveStackLowerCoerce: String? { + stackLowerCoerce ?? lowerCoerce + } +} + +/// Captures the WASM ABI shape for a ``BridgeType`` so codegen can read descriptor fields +/// instead of switching on every concrete type. +/// +/// `wasmReturnType` is for the export direction (Swift->JS), `importReturnType` for import +/// (JS->Swift). They differ for types like `string` and `associatedValueEnum` where the +/// import side returns a pointer/ID while the export side uses the stack. +public struct BridgeTypeDescriptor: Sendable { + public let wasmParams: [(name: String, type: WasmCoreType)] + public let importParams: [(name: String, type: WasmCoreType)] + public let wasmReturnType: WasmCoreType? + public let importReturnType: WasmCoreType? + public let optionalConvention: OptionalConvention + public let nilSentinel: NilSentinel + public let usesStackLifting: Bool + public let accessorTransform: AccessorTransform + public let lowerMethod: LowerMethod + public let jsCoercion: JSCoercion? + + public init( + wasmParams: [(name: String, type: WasmCoreType)], + importParams: [(name: String, type: WasmCoreType)]? = nil, + wasmReturnType: WasmCoreType?, + importReturnType: WasmCoreType? = nil, + optionalConvention: OptionalConvention, + nilSentinel: NilSentinel = .none, + usesStackLifting: Bool = false, + accessorTransform: AccessorTransform, + lowerMethod: LowerMethod, + jsCoercion: JSCoercion? = nil + ) { + self.wasmParams = wasmParams + self.importParams = importParams ?? wasmParams + self.wasmReturnType = wasmReturnType + self.importReturnType = importReturnType ?? wasmReturnType + self.optionalConvention = optionalConvention + self.nilSentinel = nilSentinel + self.usesStackLifting = usesStackLifting + self.accessorTransform = accessorTransform + self.lowerMethod = lowerMethod + self.jsCoercion = jsCoercion + } +} + +/// Describes how to transform a Swift accessor expression before passing it to bridge methods. +/// +/// Most types use `.identity` - the value is passed as-is. Two patterns require transformation: +/// - `@JSClass` types expose their underlying `JSObject` via a `.jsObject` member. +/// - `@JS protocol` wrapper types require a downcast from the existential to the concrete wrapper. +/// +/// Codegen uses this instead of switching on `jsObject(className)` / `swiftProtocol` cases. +public enum AccessorTransform: Sendable, Equatable { + /// Pass the value unchanged (e.g. `ret`). + case identity + /// Access a member on the value (e.g. `ret.jsObject`). Used by `@JSClass` types. + case member(String) + /// Downcast the value (e.g. `(ret as! AnyDrawable)`). Used by `@JS protocol` types. + case cast(String) + + /// Applies the transform to an accessor expression string. + public func apply(_ accessor: String) -> String { + switch self { + case .identity: return accessor + case .member(let member): return "\(accessor).\(member)" + case .cast(let typeName): return "(\(accessor) as! \(typeName))" + } + } + + public var mapClosure: String? { + switch self { + case .identity: return nil + case .member(let member): return "$0.\(member)" + case .cast(let typeName): return "$0 as! \(typeName)" + } + } + + public var flatMapClosure: String? { + switch self { + case .identity: return nil + case .member(let member): return "$0.\(member)" + case .cast(let typeName): return "$0 as? \(typeName)" + } + } + + public func applyToReturnBinding(_ expr: String, isOptional: Bool) -> String { + switch self { + case .cast: + if isOptional { + return "let ret = (\(expr)).flatMap { \(flatMapClosure!) }" + } + return "let ret = \(apply(expr))" + case .identity, .member: + return "let ret = \(expr)" + } + } +} + +/// Which bridge protocol method the codegen calls to lower a value in the export direction. +public enum LowerMethod: Sendable, Equatable { + /// Calls `bridgeJSLowerStackReturn()` - pushes a scalar onto the stack (used within composites like optionals, struct fields). + case stackReturn + /// Calls `bridgeJSLowerReturn()` - serializes the entire value onto the stack (struct, array, dictionary). + case fullReturn + /// Calls `bridgeJSLowerParameter()` and pushes the i32 result. Used by associated value enums (tag + stack payload). + case pushParameter + /// No lowering (void, namespace enums). + case none +} + +extension BridgeType { + /// The ABI descriptor for this type's non-optional representation. + /// + /// This is the single source of truth for how each `BridgeType` maps to WASM ABI. + /// Codegen reads descriptor fields rather than switching on individual types. + /// For `.nullable`, returns the wrapped type's descriptor. + public var descriptor: BridgeTypeDescriptor { + switch self { + case .bool: + return BridgeTypeDescriptor( + wasmParams: [("value", .i32)], + wasmReturnType: .i32, + optionalConvention: .inlineFlag, + accessorTransform: .identity, + lowerMethod: .stackReturn, + jsCoercion: JSCoercion( + liftCoerce: "$0 !== 0", + lowerCoerce: "$0 ? 1 : 0", + varHint: "bool", + optionalScalarKind: .bool + ) + ) + case .int: + return BridgeTypeDescriptor( + wasmParams: [("value", .i32)], + wasmReturnType: .i32, + optionalConvention: .sideChannelReturn(.none), + accessorTransform: .identity, + lowerMethod: .stackReturn, + jsCoercion: JSCoercion( + stackLowerCoerce: "($0 | 0)", + varHint: "int", + optionalScalarKind: .int + ) + ) + case .uint: + return BridgeTypeDescriptor( + wasmParams: [("value", .i32)], + wasmReturnType: .i32, + optionalConvention: .sideChannelReturn(.none), + accessorTransform: .identity, + lowerMethod: .stackReturn, + jsCoercion: JSCoercion( + liftCoerce: "$0 >>> 0", + stackLowerCoerce: "($0 | 0)", + varHint: "int", + optionalScalarKind: .int + ) + ) + case .float: + return BridgeTypeDescriptor( + wasmParams: [("value", .f32)], + wasmReturnType: .f32, + optionalConvention: .sideChannelReturn(.none), + accessorTransform: .identity, + lowerMethod: .stackReturn, + jsCoercion: JSCoercion( + stackLowerCoerce: "Math.fround($0)", + varHint: "f32", + optionalScalarKind: .float + ) + ) + case .double: + return BridgeTypeDescriptor( + wasmParams: [("value", .f64)], + wasmReturnType: .f64, + optionalConvention: .sideChannelReturn(.none), + accessorTransform: .identity, + lowerMethod: .stackReturn, + jsCoercion: JSCoercion( + varHint: "f64", + optionalScalarKind: .double + ) + ) + case .string: + return BridgeTypeDescriptor( + wasmParams: [("bytes", .i32), ("length", .i32)], + importParams: [("value", .i32)], + wasmReturnType: nil, + importReturnType: .i32, + optionalConvention: .sideChannelReturn(.storage), + accessorTransform: .identity, + lowerMethod: .stackReturn + ) + case .jsObject(let className): + let transform: AccessorTransform = + if let className, className != "JSObject" { .member("jsObject") } else { .identity } + return BridgeTypeDescriptor( + wasmParams: [("value", .i32)], + wasmReturnType: .i32, + optionalConvention: .sideChannelReturn(.retainedObject), + nilSentinel: .i32(0), + accessorTransform: transform, + lowerMethod: .stackReturn + ) + case .jsValue: + return BridgeTypeDescriptor( + wasmParams: [("kind", .i32), ("payload1", .i32), ("payload2", .f64)], + wasmReturnType: nil, + optionalConvention: .inlineFlag, + accessorTransform: .identity, + lowerMethod: .stackReturn + ) + case .swiftHeapObject: + return BridgeTypeDescriptor( + wasmParams: [("pointer", .pointer)], + wasmReturnType: .pointer, + optionalConvention: .inlineFlag, + nilSentinel: .pointer, + accessorTransform: .identity, + lowerMethod: .stackReturn + ) + case .unsafePointer: + return BridgeTypeDescriptor( + wasmParams: [("pointer", .pointer)], + wasmReturnType: .pointer, + optionalConvention: .inlineFlag, + accessorTransform: .identity, + lowerMethod: .stackReturn, + jsCoercion: JSCoercion(stackLowerCoerce: "($0 | 0)", varHint: "pointer") + ) + case .swiftProtocol(let protocolName): + return BridgeTypeDescriptor( + wasmParams: [("value", .i32)], + wasmReturnType: .i32, + optionalConvention: .sideChannelReturn(.retainedObject), + nilSentinel: .i32(0), + accessorTransform: .cast("Any\(protocolName)"), + lowerMethod: .stackReturn + ) + case .caseEnum: + return BridgeTypeDescriptor( + wasmParams: [("value", .i32)], + wasmReturnType: .i32, + optionalConvention: .inlineFlag, + nilSentinel: .i32(-1), + accessorTransform: .identity, + lowerMethod: .stackReturn, + jsCoercion: JSCoercion( + stackLowerCoerce: "($0 | 0)", + varHint: "caseId", + optionalScalarKind: .int + ) + ) + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: + return BridgeTypeDescriptor( + wasmParams: [("bytes", .i32), ("length", .i32)], + importParams: [("value", .i32)], + wasmReturnType: nil, + importReturnType: .i32, + optionalConvention: .sideChannelReturn(.storage), + accessorTransform: .identity, + lowerMethod: .stackReturn + ) + case .float: + return BridgeTypeDescriptor( + wasmParams: [("value", .f32)], + wasmReturnType: .f32, + optionalConvention: .sideChannelReturn(.none), + accessorTransform: .identity, + lowerMethod: .stackReturn, + jsCoercion: JSCoercion( + stackLowerCoerce: "Math.fround($0)", + varHint: "rawValue", + optionalScalarKind: .float + ) + ) + case .double: + return BridgeTypeDescriptor( + wasmParams: [("value", .f64)], + wasmReturnType: .f64, + optionalConvention: .sideChannelReturn(.none), + accessorTransform: .identity, + lowerMethod: .stackReturn, + jsCoercion: JSCoercion( + varHint: "rawValue", + optionalScalarKind: .double + ) + ) + case .bool: + return BridgeTypeDescriptor( + wasmParams: [("value", .i32)], + wasmReturnType: .i32, + optionalConvention: .inlineFlag, + accessorTransform: .identity, + lowerMethod: .stackReturn, + jsCoercion: JSCoercion( + liftCoerce: "$0 !== 0", + lowerCoerce: "$0 ? 1 : 0", + stackLowerCoerce: "$0 ? 1 : 0", + varHint: "rawValue", + optionalScalarKind: .bool + ) + ) + case .int, .int32, .int64, .uint, .uint32, .uint64: + return BridgeTypeDescriptor( + wasmParams: [("value", .i32)], + wasmReturnType: .i32, + optionalConvention: .sideChannelReturn(.none), + accessorTransform: .identity, + lowerMethod: .stackReturn, + jsCoercion: JSCoercion( + stackLowerCoerce: "($0 | 0)", + varHint: "rawValue", + optionalScalarKind: .int + ) + ) + } + case .associatedValueEnum: + return BridgeTypeDescriptor( + wasmParams: [("caseId", .i32)], + wasmReturnType: nil, + importReturnType: .i32, + optionalConvention: .inlineFlag, + nilSentinel: .i32(-1), + usesStackLifting: true, + accessorTransform: .identity, + lowerMethod: .pushParameter + ) + case .closure(_, _): + return BridgeTypeDescriptor( + wasmParams: [("funcRef", .i32)], + wasmReturnType: .i32, + optionalConvention: .inlineFlag, + accessorTransform: .identity, + lowerMethod: .stackReturn + ) + case .swiftStruct: + return BridgeTypeDescriptor( + wasmParams: [], + importParams: [("objectId", .i32)], + wasmReturnType: nil, + importReturnType: .i32, + optionalConvention: .stackABI, + usesStackLifting: true, + accessorTransform: .identity, + lowerMethod: .fullReturn + ) + case .array: + return BridgeTypeDescriptor( + wasmParams: [], + wasmReturnType: nil, + optionalConvention: .stackABI, + usesStackLifting: true, + accessorTransform: .identity, + lowerMethod: .fullReturn + ) + case .dictionary: + return BridgeTypeDescriptor( + wasmParams: [], + wasmReturnType: nil, + optionalConvention: .stackABI, + accessorTransform: .identity, + lowerMethod: .fullReturn + ) + case .void, .namespaceEnum: + return BridgeTypeDescriptor( + wasmParams: [], + wasmReturnType: nil, + optionalConvention: .stackABI, + accessorTransform: .identity, + lowerMethod: .none + ) + case .nullable(let wrapped, _): + return wrapped.descriptor + } + } + + public var needsInlineCollectionHandling: Bool { + if case .nullable = self { return true } + if case .closure = self { return true } + return false + } +} + // MARK: - BridgeType Visitor public protocol BridgeTypeVisitor { @@ -379,39 +884,20 @@ public struct BridgeTypeWalker { } } -public struct Effects: Codable, Equatable, Sendable { - public var isAsync: Bool - public var isThrows: Bool - public var isStatic: Bool +public struct ClosureSignatureCollectorVisitor: BridgeTypeVisitor { + public var signatures: Set = [] - public init(isAsync: Bool, isThrows: Bool, isStatic: Bool = false) { - self.isAsync = isAsync - self.isThrows = isThrows - self.isStatic = isStatic + public init(signatures: Set = []) { + self.signatures = signatures } -} -// MARK: - Static Function Context - -public enum StaticContext: Codable, Equatable, Sendable { - case className(String) - case structName(String) - case enumName(String) - case namespaceEnum(String) + public mutating func visitClosure(_ signature: ClosureSignature, useJSTypedClosure: Bool) { + signatures.insert(signature) + } } // MARK: - Struct Skeleton -public struct StructField: Codable, Equatable, Sendable { - public let name: String - public let type: BridgeType - - public init(name: String, type: BridgeType) { - self.name = name - self.type = type - } -} - public struct ExportedStruct: Codable, Equatable, Sendable { public let name: String public let swiftCallName: String @@ -749,15 +1235,6 @@ public struct ExportedSkeleton: Codable { self.exposeToGlobal = exposeToGlobal } - public mutating func append(_ other: ExportedSkeleton) { - self.functions.append(contentsOf: other.functions) - self.classes.append(contentsOf: other.classes) - self.enums.append(contentsOf: other.enums) - self.structs.append(contentsOf: other.structs) - self.protocols.append(contentsOf: other.protocols) - assert(self.exposeToGlobal == other.exposeToGlobal) - } - public var isEmpty: Bool { functions.isEmpty && classes.isEmpty && enums.isEmpty && structs.isEmpty && protocols.isEmpty } @@ -1005,20 +1482,6 @@ public struct ImportedModuleSkeleton: Codable { } } -// MARK: - Closure signature collection visitor - -public struct ClosureSignatureCollectorVisitor: BridgeTypeVisitor { - public var signatures: Set = [] - - public init(signatures: Set = []) { - self.signatures = signatures - } - - public mutating func visitClosure(_ signature: ClosureSignature, useJSTypedClosure: Bool) { - signatures.insert(signature) - } -} - // MARK: - Unified Skeleton /// Unified skeleton containing both exported and imported API definitions @@ -1034,7 +1497,7 @@ public struct BridgeJSSkeleton: Codable { } } -// MARK: - BridgeType extension +// MARK: - BridgeType Extension extension BridgeType { /// Maps Swift primitive type names to BridgeType. Returns nil for unknown types. @@ -1069,49 +1532,6 @@ extension BridgeType { } } - public var abiReturnType: WasmCoreType? { - switch self { - case .void: return nil - case .bool: return .i32 - case .int, .uint: return .i32 - case .float: return .f32 - case .double: return .f64 - case .string: return nil - case .jsObject: return .i32 - case .jsValue: return nil - case .swiftHeapObject: - // UnsafeMutableRawPointer is returned as an i32 pointer - return .pointer - case .unsafePointer: - return .pointer - case .nullable: - return nil - case .caseEnum: - return .i32 - case .rawValueEnum(_, let rawType): - return rawType.wasmCoreType - case .associatedValueEnum: - return nil - case .namespaceEnum: - return nil - case .swiftProtocol: - // Protocols pass JSObject IDs as Int32 - return .i32 - case .swiftStruct: - // Structs use stack-based return (no direct WASM return type) - return nil - case .closure: - // Closures pass callback ID as Int32 - return .i32 - case .array: - // Arrays use stack-based return with length prefix (no direct WASM return type) - return nil - case .dictionary: - // Dictionaries use stack-based return with entry count (no direct WASM return type) - return nil - } - } - /// Returns true if this type is optional (nullable with null or undefined). public var isOptional: Bool { if case .nullable = self { return true } @@ -1180,42 +1600,9 @@ extension BridgeType { } } - /// Determines if an optional type requires side-channel communication for protocol property returns - /// - /// Side channels are needed when the wrapped type cannot be directly returned via WASM, - /// or when we need to distinguish null from absent value for certain primitives. - public func usesSideChannelForOptionalReturn() -> Bool { - guard case .nullable(let wrappedType, _) = self else { - return false - } - - switch wrappedType { - case .string, .int, .float, .double, .jsObject, .swiftProtocol: - return true - case .rawValueEnum(_, let rawType): - switch rawType { - case .string, .int, .float, .double: - return true - default: - return false - } - case .bool, .caseEnum, .swiftHeapObject, .associatedValueEnum: - return false - default: - return false - } - } -} - -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" - } + public var usesSideChannelForOptionalReturn: Bool { + guard case .nullable = self else { return false } + if case .sideChannelReturn = descriptor.optionalConvention { return true } + return false } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift index 3141139ca..12edb29e3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift @@ -57,10 +57,7 @@ extension Point: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -73,9 +70,9 @@ extension Point: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Point") -fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.ReverseOrder.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.ReverseOrder.swift index 8d697f8ba..1aa97108c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.ReverseOrder.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.ReverseOrder.swift @@ -11,9 +11,9 @@ public func _bjs_ClassA_linkedB_get(_ _self: UnsafeMutableRawPointer) -> Void { @_expose(wasm, "bjs_ClassA_linkedB_set") @_cdecl("bjs_ClassA_linkedB_set") -public func _bjs_ClassA_linkedB_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { +public func _bjs_ClassA_linkedB_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valuePointer: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - ClassA.bridgeJSLiftParameter(_self).linkedB = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + ClassA.bridgeJSLiftParameter(_self).linkedB = Optional.bridgeJSLiftParameter(valueIsSome, valuePointer) #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.swift index 0a0396075..b523cb4b0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.swift @@ -47,9 +47,9 @@ public func _bjs_ClassA_linkedB_get(_ _self: UnsafeMutableRawPointer) -> Void { @_expose(wasm, "bjs_ClassA_linkedB_set") @_cdecl("bjs_ClassA_linkedB_set") -public func _bjs_ClassA_linkedB_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { +public func _bjs_ClassA_linkedB_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valuePointer: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - ClassA.bridgeJSLiftParameter(_self).linkedB = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + ClassA.bridgeJSLiftParameter(_self).linkedB = Optional.bridgeJSLiftParameter(valueIsSome, valuePointer) #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.swift index e8f367f1c..c905c4239 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.swift @@ -52,10 +52,7 @@ extension Config: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_Config(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_Config(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -68,9 +65,9 @@ extension Config: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Config") -fileprivate func _bjs_struct_lower_Config(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_Config(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_Config(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_Config(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -95,10 +92,7 @@ extension MathOperations: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_MathOperations(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_MathOperations(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -111,9 +105,9 @@ extension MathOperations: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_MathOperations") -fileprivate func _bjs_struct_lower_MathOperations(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_MathOperations(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_MathOperations(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_MathOperations(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift index 3d23c6bff..588fb1cbc 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift @@ -413,10 +413,7 @@ extension Point: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -429,9 +426,9 @@ extension Point: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Point") -fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift index 7fcc4d3c7..c142fbd04 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift @@ -15,10 +15,7 @@ extension FooContainer: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_FooContainer(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_FooContainer(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -31,9 +28,9 @@ extension FooContainer: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_FooContainer") -fileprivate func _bjs_struct_lower_FooContainer(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_FooContainer(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_FooContainer(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_FooContainer(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.swift index 471d38a6c..afe88e960 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.swift @@ -1,8 +1,8 @@ @_expose(wasm, "bjs_roundTripOptionalClass") @_cdecl("bjs_roundTripOptionalClass") -public func _bjs_roundTripOptionalClass(_ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { +public func _bjs_roundTripOptionalClass(_ valueIsSome: Int32, _ valuePointer: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let ret = roundTripOptionalClass(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + let ret = roundTripOptionalClass(value: Optional.bridgeJSLiftParameter(valueIsSome, valuePointer)) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -11,9 +11,9 @@ public func _bjs_roundTripOptionalClass(_ valueIsSome: Int32, _ valueValue: Unsa @_expose(wasm, "bjs_testOptionalPropertyRoundtrip") @_cdecl("bjs_testOptionalPropertyRoundtrip") -public func _bjs_testOptionalPropertyRoundtrip(_ holderIsSome: Int32, _ holderValue: UnsafeMutableRawPointer) -> Void { +public func _bjs_testOptionalPropertyRoundtrip(_ holderIsSome: Int32, _ holderPointer: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let ret = testOptionalPropertyRoundtrip(_: Optional.bridgeJSLiftParameter(holderIsSome, holderValue)) + let ret = testOptionalPropertyRoundtrip(_: Optional.bridgeJSLiftParameter(holderIsSome, holderPointer)) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -307,9 +307,9 @@ public func _bjs_OptionalPropertyHolder_optionalGreeter_get(_ _self: UnsafeMutab @_expose(wasm, "bjs_OptionalPropertyHolder_optionalGreeter_set") @_cdecl("bjs_OptionalPropertyHolder_optionalGreeter_set") -public func _bjs_OptionalPropertyHolder_optionalGreeter_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { +public func _bjs_OptionalPropertyHolder_optionalGreeter_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valuePointer: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalGreeter = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalGreeter = Optional.bridgeJSLiftParameter(valueIsSome, valuePointer) #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift index 65ff9e67c..9ac72c497 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift @@ -544,7 +544,7 @@ public func _bjs_MyViewController_sendHelper(_ _self: UnsafeMutableRawPointer, _ @_cdecl("bjs_MyViewController_delegate_get") public func _bjs_MyViewController_delegate_get(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = MyViewController.bridgeJSLiftParameter(_self).delegate as! AnyMyViewControllerDelegate + let ret = (MyViewController.bridgeJSLiftParameter(_self).delegate as! AnyMyViewControllerDelegate) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift index 925ab5937..a7ef2926d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift @@ -729,10 +729,10 @@ extension JSTypedClosure where Signature == (Optional) -> Optional Void { +public func _invoke_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Pointer: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure - let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Pointer)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.swift index fb78c3fd0..29abcebca 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.swift @@ -28,10 +28,7 @@ extension DataPoint: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_DataPoint(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_DataPoint(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -44,9 +41,9 @@ extension DataPoint: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_DataPoint") -fileprivate func _bjs_struct_lower_DataPoint(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_DataPoint(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_DataPoint(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_DataPoint(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -90,10 +87,7 @@ extension Address: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_Address(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_Address(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -106,9 +100,9 @@ extension Address: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Address") -fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -143,10 +137,7 @@ extension Person: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_Person(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_Person(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -159,9 +150,9 @@ extension Person: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Person") -fileprivate func _bjs_struct_lower_Person(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_Person(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_Person(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_Person(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -188,10 +179,7 @@ extension Session: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_Session(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_Session(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -204,9 +192,9 @@ extension Session: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Session") -fileprivate func _bjs_struct_lower_Session(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_Session(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_Session(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_Session(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -239,10 +227,7 @@ extension Measurement: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_Measurement(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_Measurement(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -255,9 +240,9 @@ extension Measurement: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Measurement") -fileprivate func _bjs_struct_lower_Measurement(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_Measurement(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_Measurement(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_Measurement(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -280,10 +265,7 @@ extension ConfigStruct: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_ConfigStruct(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_ConfigStruct(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -296,9 +278,9 @@ extension ConfigStruct: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_ConfigStruct") -fileprivate func _bjs_struct_lower_ConfigStruct(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_ConfigStruct(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_ConfigStruct(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_ConfigStruct(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -404,10 +386,7 @@ extension Container: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_Container(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_Container(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -420,9 +399,9 @@ extension Container: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Container") -fileprivate func _bjs_struct_lower_Container(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_Container(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_Container(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_Container(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStructImports.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStructImports.swift index 089912afe..29386e65f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStructImports.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStructImports.swift @@ -11,10 +11,7 @@ extension Point: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -27,9 +24,9 @@ extension Point: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Point") -fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/UnsafePointer.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/UnsafePointer.swift index a4f372e9b..9385c0621 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/UnsafePointer.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/UnsafePointer.swift @@ -17,10 +17,7 @@ extension PointerFields: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_PointerFields(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_PointerFields(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -33,9 +30,9 @@ extension PointerFields: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_PointerFields") -fileprivate func _bjs_struct_lower_PointerFields(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_PointerFields(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_PointerFields(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_PointerFields(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js index 52438d27d..c6804a85e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js @@ -36,26 +36,22 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; let _exports = null; let bjs = null; - const __bjs_createPointHelpers = () => { - return () => ({ - lower: (value) => { - f64Stack.push(value.x); - f64Stack.push(value.y); - return { cleanup: undefined }; - }, - lift: () => { - const f64 = f64Stack.pop(); - const f641 = f64Stack.pop(); - return { x: f641, y: f64 }; - } - }); - }; + const __bjs_createPointHelpers = () => ({ + lower: (value) => { + f64Stack.push(value.x); + f64Stack.push(value.y); + }, + lift: () => { + const f64 = f64Stack.pop(); + const f641 = f64Stack.pop(); + return { x: f641, y: f64 }; + } + }); return { /** @@ -104,8 +100,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -122,22 +117,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_struct_lower_Point"] = function(objectId) { - const { cleanup: cleanup } = structHelpers.Point.lower(swift.memory.getObject(objectId)); - if (cleanup) { - return tmpStructCleanups.push(cleanup); - } - return 0; + structHelpers.Point.lower(swift.memory.getObject(objectId)); } bjs["swift_js_struct_lift_Point"] = function() { const value = structHelpers.Point.lift(); @@ -274,7 +255,6 @@ export async function createInstantiator(options, swift) { TestModule["bjs_importGetNumbers"] = function bjs_importGetNumbers() { try { let ret = imports.importGetNumbers(); - const arrayCleanups = []; for (const elem of ret) { f64Stack.push(elem); } @@ -293,7 +273,6 @@ export async function createInstantiator(options, swift) { } arrayResult.reverse(); let ret = imports.importTransformNumbers(arrayResult); - const arrayCleanups = []; for (const elem of ret) { f64Stack.push(elem); } @@ -312,7 +291,6 @@ export async function createInstantiator(options, swift) { } arrayResult.reverse(); let ret = imports.importProcessStrings(arrayResult); - const arrayCleanups = []; for (const elem of ret) { const bytes = textEncoder.encode(elem); const id = swift.memory.retain(bytes); @@ -334,7 +312,6 @@ export async function createInstantiator(options, swift) { } arrayResult.reverse(); let ret = imports.importProcessBooleans(arrayResult); - const arrayCleanups = []; for (const elem of ret) { i32Stack.push(elem ? 1 : 0); } @@ -380,13 +357,12 @@ export async function createInstantiator(options, swift) { } } - const PointHelpers = __bjs_createPointHelpers()(); + const PointHelpers = __bjs_createPointHelpers(); structHelpers.Point = PointHelpers; const exports = { Item, processIntArray: function bjs_processIntArray(values) { - const arrayCleanups = []; for (const elem of values) { i32Stack.push((elem | 0)); } @@ -399,11 +375,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(int); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processStringArray: function bjs_processStringArray(values) { - const arrayCleanups = []; for (const elem of values) { const bytes = textEncoder.encode(elem); const id = swift.memory.retain(bytes); @@ -419,11 +393,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(string); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processDoubleArray: function bjs_processDoubleArray(values) { - const arrayCleanups = []; for (const elem of values) { f64Stack.push(elem); } @@ -436,11 +408,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(f64); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processBoolArray: function bjs_processBoolArray(values) { - const arrayCleanups = []; for (const elem of values) { i32Stack.push(elem ? 1 : 0); } @@ -453,16 +423,11 @@ export async function createInstantiator(options, swift) { arrayResult.push(bool); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processPointArray: function bjs_processPointArray(points) { - const arrayCleanups = []; for (const elem of points) { - const { cleanup: structCleanup } = structHelpers.Point.lower(elem); - arrayCleanups.push(() => { - if (structCleanup) { structCleanup(); } - }); + structHelpers.Point.lower(elem); } i32Stack.push(points.length); instance.exports.bjs_processPointArray(); @@ -473,11 +438,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(struct); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processDirectionArray: function bjs_processDirectionArray(directions) { - const arrayCleanups = []; for (const elem of directions) { i32Stack.push((elem | 0)); } @@ -490,11 +453,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(caseId); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processStatusArray: function bjs_processStatusArray(statuses) { - const arrayCleanups = []; for (const elem of statuses) { i32Stack.push((elem | 0)); } @@ -507,37 +468,28 @@ export async function createInstantiator(options, swift) { arrayResult.push(rawValue); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, sumIntArray: function bjs_sumIntArray(values) { - const arrayCleanups = []; for (const elem of values) { i32Stack.push((elem | 0)); } i32Stack.push(values.length); const ret = instance.exports.bjs_sumIntArray(); - for (const cleanup of arrayCleanups) { cleanup(); } return ret; }, findFirstPoint: function bjs_findFirstPoint(points, matching) { - const arrayCleanups = []; for (const elem of points) { - const { cleanup: structCleanup } = structHelpers.Point.lower(elem); - arrayCleanups.push(() => { - if (structCleanup) { structCleanup(); } - }); + structHelpers.Point.lower(elem); } i32Stack.push(points.length); const matchingBytes = textEncoder.encode(matching); const matchingId = swift.memory.retain(matchingBytes); instance.exports.bjs_findFirstPoint(matchingId, matchingBytes.length); const structValue = structHelpers.Point.lift(); - for (const cleanup of arrayCleanups) { cleanup(); } return structValue; }, processUnsafeRawPointerArray: function bjs_processUnsafeRawPointerArray(values) { - const arrayCleanups = []; for (const elem of values) { ptrStack.push((elem | 0)); } @@ -550,11 +502,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(pointer); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processUnsafeMutableRawPointerArray: function bjs_processUnsafeMutableRawPointerArray(values) { - const arrayCleanups = []; for (const elem of values) { ptrStack.push((elem | 0)); } @@ -567,11 +517,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(pointer); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processOpaquePointerArray: function bjs_processOpaquePointerArray(values) { - const arrayCleanups = []; for (const elem of values) { ptrStack.push((elem | 0)); } @@ -584,11 +532,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(pointer); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processOptionalIntArray: function bjs_processOptionalIntArray(values) { - const arrayCleanups = []; for (const elem of values) { const isSome = elem != null ? 1 : 0; if (isSome) { @@ -614,11 +560,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(optValue); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processOptionalStringArray: function bjs_processOptionalStringArray(values) { - const arrayCleanups = []; for (const elem of values) { const isSome = elem != null ? 1 : 0; if (isSome) { @@ -648,19 +592,15 @@ export async function createInstantiator(options, swift) { arrayResult.push(optValue); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processOptionalArray: function bjs_processOptionalArray(values) { const isSome = values != null; - const valuesCleanups = []; if (isSome) { - const arrayCleanups = []; for (const elem of values) { i32Stack.push((elem | 0)); } i32Stack.push(values.length); - valuesCleanups.push(() => { for (const cleanup of arrayCleanups) { cleanup(); } }); } i32Stack.push(+isSome); instance.exports.bjs_processOptionalArray(); @@ -678,17 +618,13 @@ export async function createInstantiator(options, swift) { } else { optResult = null; } - for (const cleanup of valuesCleanups) { cleanup(); } return optResult; }, processOptionalPointArray: function bjs_processOptionalPointArray(points) { - const arrayCleanups = []; for (const elem of points) { const isSome = elem != null ? 1 : 0; if (isSome) { - const { cleanup: structCleanup } = structHelpers.Point.lower(elem); - arrayCleanups.push(() => { if (structCleanup) { structCleanup(); } }); - } else { + structHelpers.Point.lower(elem); } i32Stack.push(isSome); } @@ -708,11 +644,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(optValue); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processOptionalDirectionArray: function bjs_processOptionalDirectionArray(directions) { - const arrayCleanups = []; for (const elem of directions) { const isSome = elem != null ? 1 : 0; if (isSome) { @@ -738,11 +672,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(optValue); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processOptionalStatusArray: function bjs_processOptionalStatusArray(statuses) { - const arrayCleanups = []; for (const elem of statuses) { const isSome = elem != null ? 1 : 0; if (isSome) { @@ -768,20 +700,14 @@ export async function createInstantiator(options, swift) { arrayResult.push(optValue); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processNestedIntArray: function bjs_processNestedIntArray(values) { - const arrayCleanups = []; for (const elem of values) { - const arrayCleanups1 = []; for (const elem1 of elem) { i32Stack.push((elem1 | 0)); } i32Stack.push(elem.length); - arrayCleanups.push(() => { - for (const cleanup of arrayCleanups1) { cleanup(); } - }); } i32Stack.push(values.length); instance.exports.bjs_processNestedIntArray(); @@ -798,13 +724,10 @@ export async function createInstantiator(options, swift) { arrayResult.push(arrayResult1); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processNestedStringArray: function bjs_processNestedStringArray(values) { - const arrayCleanups = []; for (const elem of values) { - const arrayCleanups1 = []; for (const elem1 of elem) { const bytes = textEncoder.encode(elem1); const id = swift.memory.retain(bytes); @@ -812,9 +735,6 @@ export async function createInstantiator(options, swift) { i32Stack.push(id); } i32Stack.push(elem.length); - arrayCleanups.push(() => { - for (const cleanup of arrayCleanups1) { cleanup(); } - }); } i32Stack.push(values.length); instance.exports.bjs_processNestedStringArray(); @@ -831,23 +751,14 @@ export async function createInstantiator(options, swift) { arrayResult.push(arrayResult1); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processNestedPointArray: function bjs_processNestedPointArray(points) { - const arrayCleanups = []; for (const elem of points) { - const arrayCleanups1 = []; for (const elem1 of elem) { - const { cleanup: structCleanup } = structHelpers.Point.lower(elem1); - arrayCleanups1.push(() => { - if (structCleanup) { structCleanup(); } - }); + structHelpers.Point.lower(elem1); } i32Stack.push(elem.length); - arrayCleanups.push(() => { - for (const cleanup of arrayCleanups1) { cleanup(); } - }); } i32Stack.push(points.length); instance.exports.bjs_processNestedPointArray(); @@ -864,11 +775,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(arrayResult1); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processItemArray: function bjs_processItemArray(items) { - const arrayCleanups = []; for (const elem of items) { ptrStack.push(elem.pointer); } @@ -882,20 +791,14 @@ export async function createInstantiator(options, swift) { arrayResult.push(obj); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processNestedItemArray: function bjs_processNestedItemArray(items) { - const arrayCleanups = []; for (const elem of items) { - const arrayCleanups1 = []; for (const elem1 of elem) { ptrStack.push(elem1.pointer); } i32Stack.push(elem.length); - arrayCleanups.push(() => { - for (const cleanup of arrayCleanups1) { cleanup(); } - }); } i32Stack.push(items.length); instance.exports.bjs_processNestedItemArray(); @@ -913,11 +816,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(arrayResult1); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processJSObjectArray: function bjs_processJSObjectArray(objects) { - const arrayCleanups = []; for (const elem of objects) { const objId = swift.memory.retain(elem); i32Stack.push(objId); @@ -933,11 +834,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(obj); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processOptionalJSObjectArray: function bjs_processOptionalJSObjectArray(objects) { - const arrayCleanups = []; for (const elem of objects) { const isSome = elem != null ? 1 : 0; if (isSome) { @@ -966,21 +865,15 @@ export async function createInstantiator(options, swift) { arrayResult.push(optValue); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processNestedJSObjectArray: function bjs_processNestedJSObjectArray(objects) { - const arrayCleanups = []; for (const elem of objects) { - const arrayCleanups1 = []; for (const elem1 of elem) { const objId = swift.memory.retain(elem1); i32Stack.push(objId); } i32Stack.push(elem.length); - arrayCleanups.push(() => { - for (const cleanup of arrayCleanups1) { cleanup(); } - }); } i32Stack.push(objects.length); instance.exports.bjs_processNestedJSObjectArray(); @@ -999,7 +892,6 @@ export async function createInstantiator(options, swift) { arrayResult.push(arrayResult1); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, Direction: DirectionValues, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js index bd57f0fd4..3ec0af319 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -76,8 +75,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -94,16 +92,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js index 6182298a1..342ae514f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js @@ -29,56 +29,47 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; let _exports = null; let bjs = null; - const __bjs_createConfigHelpers = () => { - return () => ({ - lower: (value) => { - const bytes = textEncoder.encode(value.name); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - i32Stack.push((value.value | 0)); - i32Stack.push(value.enabled ? 1 : 0); - return { cleanup: undefined }; - }, - lift: () => { - const bool = i32Stack.pop() !== 0; - const int = i32Stack.pop(); - const string = strStack.pop(); - return { name: string, value: int, enabled: bool }; - } - }); - }; - const __bjs_createMathOperationsHelpers = () => { - return () => ({ - lower: (value) => { - f64Stack.push(value.baseValue); - return { cleanup: undefined }; - }, - lift: () => { - const f64 = f64Stack.pop(); - const instance1 = { baseValue: f64 }; - instance1.add = function(a, b = 10.0) { - const { cleanup: structCleanup } = structHelpers.MathOperations.lower(this); - const ret = instance.exports.bjs_MathOperations_add(a, b); - if (structCleanup) { structCleanup(); } - return ret; - }.bind(instance1); - instance1.multiply = function(a, b) { - const { cleanup: structCleanup } = structHelpers.MathOperations.lower(this); - const ret = instance.exports.bjs_MathOperations_multiply(a, b); - if (structCleanup) { structCleanup(); } - return ret; - }.bind(instance1); - return instance1; - } - }); - }; + const __bjs_createConfigHelpers = () => ({ + lower: (value) => { + const bytes = textEncoder.encode(value.name); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + i32Stack.push((value.value | 0)); + i32Stack.push(value.enabled ? 1 : 0); + }, + lift: () => { + const bool = i32Stack.pop() !== 0; + const int = i32Stack.pop(); + const string = strStack.pop(); + return { name: string, value: int, enabled: bool }; + } + }); + const __bjs_createMathOperationsHelpers = () => ({ + lower: (value) => { + f64Stack.push(value.baseValue); + }, + lift: () => { + const f64 = f64Stack.pop(); + const instance1 = { baseValue: f64 }; + instance1.add = function(a, b = 10.0) { + structHelpers.MathOperations.lower(this); + const ret = instance.exports.bjs_MathOperations_add(a, b); + return ret; + }.bind(instance1); + instance1.multiply = function(a, b) { + structHelpers.MathOperations.lower(this); + const ret = instance.exports.bjs_MathOperations_multiply(a, b); + return ret; + }.bind(instance1); + return instance1; + } + }); return { /** @@ -126,8 +117,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -144,33 +134,15 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_struct_lower_Config"] = function(objectId) { - const { cleanup: cleanup } = structHelpers.Config.lower(swift.memory.getObject(objectId)); - if (cleanup) { - return tmpStructCleanups.push(cleanup); - } - return 0; + structHelpers.Config.lower(swift.memory.getObject(objectId)); } bjs["swift_js_struct_lift_Config"] = function() { const value = structHelpers.Config.lift(); return swift.memory.retain(value); } bjs["swift_js_struct_lower_MathOperations"] = function(objectId) { - const { cleanup: cleanup } = structHelpers.MathOperations.lower(swift.memory.getObject(objectId)); - if (cleanup) { - return tmpStructCleanups.push(cleanup); - } - return 0; + structHelpers.MathOperations.lower(swift.memory.getObject(objectId)); } bjs["swift_js_struct_lift_MathOperations"] = function() { const value = structHelpers.MathOperations.lift(); @@ -356,12 +328,18 @@ export async function createInstantiator(options, swift) { const nameBytes = textEncoder.encode(name); const nameId = swift.memory.retain(nameBytes); const isSome = tag != null; - let tagId, tagBytes; + let result; + let result1; if (isSome) { - tagBytes = textEncoder.encode(tag); - tagId = swift.memory.retain(tagBytes); + const tagBytes = textEncoder.encode(tag); + const tagId = swift.memory.retain(tagBytes); + result = tagId; + result1 = tagBytes.length; + } else { + result = 0; + result1 = 0; } - const ret = instance.exports.bjs_ConstructorDefaults_init(nameId, nameBytes.length, count, enabled, status, +isSome, isSome ? tagId : 0, isSome ? tagBytes.length : 0); + const ret = instance.exports.bjs_ConstructorDefaults_init(nameId, nameBytes.length, count, enabled, status, +isSome, result, result1); return ConstructorDefaults.__construct(ret); } get name() { @@ -404,18 +382,24 @@ export async function createInstantiator(options, swift) { } set tag(value) { const isSome = value != null; - let valueId, valueBytes; + let result; + let result1; if (isSome) { - valueBytes = textEncoder.encode(value); - valueId = swift.memory.retain(valueBytes); + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + result = valueId; + result1 = valueBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_ConstructorDefaults_tag_set(this.pointer, +isSome, isSome ? valueId : 0, isSome ? valueBytes.length : 0); + instance.exports.bjs_ConstructorDefaults_tag_set(this.pointer, +isSome, result, result1); } } - const ConfigHelpers = __bjs_createConfigHelpers()(); + const ConfigHelpers = __bjs_createConfigHelpers(); structHelpers.Config = ConfigHelpers; - const MathOperationsHelpers = __bjs_createMathOperationsHelpers()(); + const MathOperationsHelpers = __bjs_createMathOperationsHelpers(); structHelpers.MathOperations = MathOperationsHelpers; const exports = { @@ -448,24 +432,36 @@ export async function createInstantiator(options, swift) { }, testOptionalDefault: function bjs_testOptionalDefault(name = null) { const isSome = name != null; - let nameId, nameBytes; + let result; + let result1; if (isSome) { - nameBytes = textEncoder.encode(name); - nameId = swift.memory.retain(nameBytes); + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + result = nameId; + result1 = nameBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_testOptionalDefault(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + instance.exports.bjs_testOptionalDefault(+isSome, result, result1); const optResult = tmpRetString; tmpRetString = undefined; return optResult; }, testOptionalStringDefault: function bjs_testOptionalStringDefault(greeting = "Hi") { const isSome = greeting != null; - let greetingId, greetingBytes; + let result; + let result1; if (isSome) { - greetingBytes = textEncoder.encode(greeting); - greetingId = swift.memory.retain(greetingBytes); + const greetingBytes = textEncoder.encode(greeting); + const greetingId = swift.memory.retain(greetingBytes); + result = greetingId; + result1 = greetingBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_testOptionalStringDefault(+isSome, isSome ? greetingId : 0, isSome ? greetingBytes.length : 0); + instance.exports.bjs_testOptionalStringDefault(+isSome, result, result1); const optResult = tmpRetString; tmpRetString = undefined; return optResult; @@ -492,44 +488,27 @@ export async function createInstantiator(options, swift) { }, testOptionalStructDefault: function bjs_testOptionalStructDefault(point = null) { const isSome = point != null; - let pointCleanup; if (isSome) { - const structResult = structHelpers.Config.lower(point); - pointCleanup = structResult.cleanup; + structHelpers.Config.lower(point); } i32Stack.push(+isSome); instance.exports.bjs_testOptionalStructDefault(); const isSome1 = i32Stack.pop(); - let optResult; - if (isSome1) { - optResult = structHelpers.Config.lift(); - } else { - optResult = null; - } - if (pointCleanup) { pointCleanup(); } + const optResult = isSome1 ? structHelpers.Config.lift() : null; return optResult; }, testOptionalStructWithValueDefault: function bjs_testOptionalStructWithValueDefault(point = { name: "default", value: 42, enabled: true }) { const isSome = point != null; - let pointCleanup; if (isSome) { - const structResult = structHelpers.Config.lower(point); - pointCleanup = structResult.cleanup; + structHelpers.Config.lower(point); } i32Stack.push(+isSome); instance.exports.bjs_testOptionalStructWithValueDefault(); const isSome1 = i32Stack.pop(); - let optResult; - if (isSome1) { - optResult = structHelpers.Config.lift(); - } else { - optResult = null; - } - if (pointCleanup) { pointCleanup(); } + const optResult = isSome1 ? structHelpers.Config.lift() : null; return optResult; }, testIntArrayDefault: function bjs_testIntArrayDefault(values = [1, 2, 3]) { - const arrayCleanups = []; for (const elem of values) { i32Stack.push((elem | 0)); } @@ -542,11 +521,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(int); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, testStringArrayDefault: function bjs_testStringArrayDefault(names = ["a", "b", "c"]) { - const arrayCleanups = []; for (const elem of names) { const bytes = textEncoder.encode(elem); const id = swift.memory.retain(bytes); @@ -562,11 +539,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(string); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, testDoubleArrayDefault: function bjs_testDoubleArrayDefault(values = [1.5, 2.5, 3.5]) { - const arrayCleanups = []; for (const elem of values) { f64Stack.push(elem); } @@ -579,11 +554,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(f64); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, testBoolArrayDefault: function bjs_testBoolArrayDefault(flags = [true, false, true]) { - const arrayCleanups = []; for (const elem of flags) { i32Stack.push(elem ? 1 : 0); } @@ -596,11 +569,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(bool); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, testEmptyArrayDefault: function bjs_testEmptyArrayDefault(items = []) { - const arrayCleanups = []; for (const elem of items) { i32Stack.push((elem | 0)); } @@ -613,13 +584,11 @@ export async function createInstantiator(options, swift) { arrayResult.push(int); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, testMixedWithArrayDefault: function bjs_testMixedWithArrayDefault(name = "test", values = [10, 20, 30], enabled = true) { const nameBytes = textEncoder.encode(name); const nameId = swift.memory.retain(nameBytes); - const arrayCleanups = []; for (const elem of values) { i32Stack.push((elem | 0)); } @@ -627,7 +596,6 @@ export async function createInstantiator(options, swift) { instance.exports.bjs_testMixedWithArrayDefault(nameId, nameBytes.length, enabled); const ret = tmpRetString; tmpRetString = undefined; - for (const cleanup of arrayCleanups) { cleanup(); } return ret; }, Status: StatusValues, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js index 4f71aa76e..5b0519402 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -77,8 +76,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -95,16 +93,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -215,7 +203,6 @@ export async function createInstantiator(options, swift) { dictResult[string] = f64; } let ret = imports.importMirrorDictionary(dictResult); - const arrayCleanups = []; const entries = Object.entries(ret); for (const entry of entries) { const [key, value] = entry; @@ -270,7 +257,6 @@ export async function createInstantiator(options, swift) { const exports = { Box, mirrorDictionary: function bjs_mirrorDictionary(values) { - const arrayCleanups = []; const entries = Object.entries(values); for (const entry of entries) { const [key, value] = entry; @@ -289,14 +275,11 @@ export async function createInstantiator(options, swift) { const string = strStack.pop(); dictResult[string] = int; } - for (const cleanup of arrayCleanups) { cleanup(); } return dictResult; }, optionalDictionary: function bjs_optionalDictionary(values) { const isSome = values != null; - const valuesCleanups = []; if (isSome) { - const arrayCleanups = []; const entries = Object.entries(values); for (const entry of entries) { const [key, value] = entry; @@ -310,7 +293,6 @@ export async function createInstantiator(options, swift) { i32Stack.push(id1); } i32Stack.push(entries.length); - valuesCleanups.push(() => { for (const cleanup of arrayCleanups) { cleanup(); } }); } i32Stack.push(+isSome); instance.exports.bjs_optionalDictionary(); @@ -328,11 +310,9 @@ export async function createInstantiator(options, swift) { } else { optResult = null; } - for (const cleanup of valuesCleanups) { cleanup(); } return optResult; }, nestedDictionary: function bjs_nestedDictionary(values) { - const arrayCleanups = []; const entries = Object.entries(values); for (const entry of entries) { const [key, value] = entry; @@ -340,14 +320,10 @@ export async function createInstantiator(options, swift) { const id = swift.memory.retain(bytes); i32Stack.push(bytes.length); i32Stack.push(id); - const arrayCleanups1 = []; for (const elem of value) { i32Stack.push((elem | 0)); } i32Stack.push(value.length); - arrayCleanups.push(() => { - for (const cleanup of arrayCleanups1) { cleanup(); } - }); } i32Stack.push(entries.length); instance.exports.bjs_nestedDictionary(); @@ -364,11 +340,9 @@ export async function createInstantiator(options, swift) { const string = strStack.pop(); dictResult[string] = arrayResult; } - for (const cleanup of arrayCleanups) { cleanup(); } return dictResult; }, boxDictionary: function bjs_boxDictionary(boxes) { - const arrayCleanups = []; const entries = Object.entries(boxes); for (const entry of entries) { const [key, value] = entry; @@ -388,11 +362,9 @@ export async function createInstantiator(options, swift) { const string = strStack.pop(); dictResult[string] = obj; } - for (const cleanup of arrayCleanups) { cleanup(); } return dictResult; }, optionalBoxDictionary: function bjs_optionalBoxDictionary(boxes) { - const arrayCleanups = []; const entries = Object.entries(boxes); for (const entry of entries) { const [key, value] = entry; @@ -425,7 +397,6 @@ export async function createInstantiator(options, swift) { const string = strStack.pop(); dictResult[string] = optValue; } - for (const cleanup of arrayCleanups) { cleanup(); } return dictResult; }, }; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js index af81d52fe..4660f5c54 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js @@ -104,573 +104,645 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; let _exports = null; let bjs = null; - const __bjs_createPointHelpers = () => { - return () => ({ - lower: (value) => { - f64Stack.push(value.x); - f64Stack.push(value.y); - return { cleanup: undefined }; - }, - lift: () => { - const f64 = f64Stack.pop(); - const f641 = f64Stack.pop(); - return { x: f641, y: f64 }; + const __bjs_createPointHelpers = () => ({ + lower: (value) => { + f64Stack.push(value.x); + f64Stack.push(value.y); + }, + lift: () => { + const f64 = f64Stack.pop(); + const f641 = f64Stack.pop(); + return { x: f641, y: f64 }; + } + }); + const __bjs_createAPIResultValuesHelpers = () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case APIResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + return APIResultValues.Tag.Success; + } + case APIResultValues.Tag.Failure: { + i32Stack.push((value.param0 | 0)); + return APIResultValues.Tag.Failure; + } + case APIResultValues.Tag.Flag: { + i32Stack.push(value.param0 ? 1 : 0); + return APIResultValues.Tag.Flag; + } + case APIResultValues.Tag.Rate: { + f32Stack.push(Math.fround(value.param0)); + return APIResultValues.Tag.Rate; + } + case APIResultValues.Tag.Precise: { + f64Stack.push(value.param0); + return APIResultValues.Tag.Precise; + } + case APIResultValues.Tag.Info: { + return APIResultValues.Tag.Info; + } + default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); } - }); - }; - const __bjs_createAPIResultValuesHelpers = () => { - return () => ({ - lower: (value) => { - const enumTag = value.tag; - switch (enumTag) { - case APIResultValues.Tag.Success: { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - const cleanup = undefined; - return { caseId: APIResultValues.Tag.Success, cleanup }; - } - case APIResultValues.Tag.Failure: { - i32Stack.push((value.param0 | 0)); - const cleanup = undefined; - return { caseId: APIResultValues.Tag.Failure, cleanup }; - } - case APIResultValues.Tag.Flag: { - i32Stack.push(value.param0 ? 1 : 0); - const cleanup = undefined; - return { caseId: APIResultValues.Tag.Flag, cleanup }; - } - case APIResultValues.Tag.Rate: { - f32Stack.push(Math.fround(value.param0)); - const cleanup = undefined; - return { caseId: APIResultValues.Tag.Rate, cleanup }; - } - case APIResultValues.Tag.Precise: { - f64Stack.push(value.param0); - const cleanup = undefined; - return { caseId: APIResultValues.Tag.Precise, cleanup }; - } - case APIResultValues.Tag.Info: { - const cleanup = undefined; - return { caseId: APIResultValues.Tag.Info, cleanup }; - } - default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case APIResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: APIResultValues.Tag.Success, param0: string }; } - }, - lift: (tag) => { - tag = tag | 0; - switch (tag) { - case APIResultValues.Tag.Success: { - const string = strStack.pop(); - return { tag: APIResultValues.Tag.Success, param0: string }; - } - case APIResultValues.Tag.Failure: { - const int = i32Stack.pop(); - return { tag: APIResultValues.Tag.Failure, param0: int }; - } - case APIResultValues.Tag.Flag: { - const bool = i32Stack.pop() !== 0; - return { tag: APIResultValues.Tag.Flag, param0: bool }; - } - case APIResultValues.Tag.Rate: { - const f32 = f32Stack.pop(); - return { tag: APIResultValues.Tag.Rate, param0: f32 }; - } - case APIResultValues.Tag.Precise: { - const f64 = f64Stack.pop(); - return { tag: APIResultValues.Tag.Precise, param0: f64 }; - } - case APIResultValues.Tag.Info: return { tag: APIResultValues.Tag.Info }; - default: throw new Error("Unknown APIResultValues tag returned from Swift: " + String(tag)); + case APIResultValues.Tag.Failure: { + const int = i32Stack.pop(); + return { tag: APIResultValues.Tag.Failure, param0: int }; } + case APIResultValues.Tag.Flag: { + const bool = i32Stack.pop() !== 0; + return { tag: APIResultValues.Tag.Flag, param0: bool }; + } + case APIResultValues.Tag.Rate: { + const f32 = f32Stack.pop(); + return { tag: APIResultValues.Tag.Rate, param0: f32 }; + } + case APIResultValues.Tag.Precise: { + const f64 = f64Stack.pop(); + return { tag: APIResultValues.Tag.Precise, param0: f64 }; + } + case APIResultValues.Tag.Info: return { tag: APIResultValues.Tag.Info }; + default: throw new Error("Unknown APIResultValues tag returned from Swift: " + String(tag)); } - }); - }; - const __bjs_createComplexResultValuesHelpers = () => { - return () => ({ - lower: (value) => { - const enumTag = value.tag; - switch (enumTag) { - case ComplexResultValues.Tag.Success: { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - const cleanup = undefined; - return { caseId: ComplexResultValues.Tag.Success, cleanup }; - } - case ComplexResultValues.Tag.Error: { - i32Stack.push((value.param1 | 0)); + } + }); + const __bjs_createComplexResultValuesHelpers = () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case ComplexResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + return ComplexResultValues.Tag.Success; + } + case ComplexResultValues.Tag.Error: { + i32Stack.push((value.param1 | 0)); + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + return ComplexResultValues.Tag.Error; + } + case ComplexResultValues.Tag.Status: { + const bytes = textEncoder.encode(value.param2); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + i32Stack.push((value.param1 | 0)); + i32Stack.push(value.param0 ? 1 : 0); + return ComplexResultValues.Tag.Status; + } + case ComplexResultValues.Tag.Coordinates: { + f64Stack.push(value.param2); + f64Stack.push(value.param1); + f64Stack.push(value.param0); + return ComplexResultValues.Tag.Coordinates; + } + case ComplexResultValues.Tag.Comprehensive: { + const bytes = textEncoder.encode(value.param8); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const bytes1 = textEncoder.encode(value.param7); + const id1 = swift.memory.retain(bytes1); + i32Stack.push(bytes1.length); + i32Stack.push(id1); + const bytes2 = textEncoder.encode(value.param6); + const id2 = swift.memory.retain(bytes2); + i32Stack.push(bytes2.length); + i32Stack.push(id2); + f64Stack.push(value.param5); + f64Stack.push(value.param4); + i32Stack.push((value.param3 | 0)); + i32Stack.push((value.param2 | 0)); + i32Stack.push(value.param1 ? 1 : 0); + i32Stack.push(value.param0 ? 1 : 0); + return ComplexResultValues.Tag.Comprehensive; + } + case ComplexResultValues.Tag.Info: { + return ComplexResultValues.Tag.Info; + } + default: throw new Error("Unknown ComplexResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case ComplexResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: ComplexResultValues.Tag.Success, param0: string }; + } + case ComplexResultValues.Tag.Error: { + const int = i32Stack.pop(); + const string = strStack.pop(); + return { tag: ComplexResultValues.Tag.Error, param0: string, param1: int }; + } + case ComplexResultValues.Tag.Status: { + const string = strStack.pop(); + const int = i32Stack.pop(); + const bool = i32Stack.pop() !== 0; + return { tag: ComplexResultValues.Tag.Status, param0: bool, param1: int, param2: string }; + } + case ComplexResultValues.Tag.Coordinates: { + const f64 = f64Stack.pop(); + const f641 = f64Stack.pop(); + const f642 = f64Stack.pop(); + return { tag: ComplexResultValues.Tag.Coordinates, param0: f642, param1: f641, param2: f64 }; + } + case ComplexResultValues.Tag.Comprehensive: { + const string = strStack.pop(); + const string1 = strStack.pop(); + const string2 = strStack.pop(); + const f64 = f64Stack.pop(); + const f641 = f64Stack.pop(); + const int = i32Stack.pop(); + const int1 = i32Stack.pop(); + const bool = i32Stack.pop() !== 0; + const bool1 = i32Stack.pop() !== 0; + return { tag: ComplexResultValues.Tag.Comprehensive, param0: bool1, param1: bool, param2: int1, param3: int, param4: f641, param5: f64, param6: string2, param7: string1, param8: string }; + } + case ComplexResultValues.Tag.Info: return { tag: ComplexResultValues.Tag.Info }; + default: throw new Error("Unknown ComplexResultValues tag returned from Swift: " + String(tag)); + } + } + }); + const __bjs_createResultValuesHelpers = () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case ResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + return ResultValues.Tag.Success; + } + case ResultValues.Tag.Failure: { + i32Stack.push((value.param1 | 0)); + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + return ResultValues.Tag.Failure; + } + case ResultValues.Tag.Status: { + const bytes = textEncoder.encode(value.param2); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + i32Stack.push((value.param1 | 0)); + i32Stack.push(value.param0 ? 1 : 0); + return ResultValues.Tag.Status; + } + default: throw new Error("Unknown ResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case ResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: ResultValues.Tag.Success, param0: string }; + } + case ResultValues.Tag.Failure: { + const int = i32Stack.pop(); + const string = strStack.pop(); + return { tag: ResultValues.Tag.Failure, param0: string, param1: int }; + } + case ResultValues.Tag.Status: { + const string = strStack.pop(); + const int = i32Stack.pop(); + const bool = i32Stack.pop() !== 0; + return { tag: ResultValues.Tag.Status, param0: bool, param1: int, param2: string }; + } + default: throw new Error("Unknown ResultValues tag returned from Swift: " + String(tag)); + } + } + }); + const __bjs_createNetworkingResultValuesHelpers = () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case NetworkingResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + return NetworkingResultValues.Tag.Success; + } + case NetworkingResultValues.Tag.Failure: { + i32Stack.push((value.param1 | 0)); + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + return NetworkingResultValues.Tag.Failure; + } + default: throw new Error("Unknown NetworkingResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case NetworkingResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: NetworkingResultValues.Tag.Success, param0: string }; + } + case NetworkingResultValues.Tag.Failure: { + const int = i32Stack.pop(); + const string = strStack.pop(); + return { tag: NetworkingResultValues.Tag.Failure, param0: string, param1: int }; + } + default: throw new Error("Unknown NetworkingResultValues tag returned from Swift: " + String(tag)); + } + } + }); + const __bjs_createAPIOptionalResultValuesHelpers = () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case APIOptionalResultValues.Tag.Success: { + const isSome = value.param0 != null; + if (isSome) { const bytes = textEncoder.encode(value.param0); const id = swift.memory.retain(bytes); i32Stack.push(bytes.length); i32Stack.push(id); - const cleanup = undefined; - return { caseId: ComplexResultValues.Tag.Error, cleanup }; + } else { + i32Stack.push(0); + i32Stack.push(0); } - case ComplexResultValues.Tag.Status: { + i32Stack.push(isSome ? 1 : 0); + return APIOptionalResultValues.Tag.Success; + } + case APIOptionalResultValues.Tag.Failure: { + const isSome = value.param1 != null; + i32Stack.push(isSome ? (value.param1 ? 1 : 0) : 0); + i32Stack.push(isSome ? 1 : 0); + const isSome1 = value.param0 != null; + i32Stack.push(isSome1 ? (value.param0 | 0) : 0); + i32Stack.push(isSome1 ? 1 : 0); + return APIOptionalResultValues.Tag.Failure; + } + case APIOptionalResultValues.Tag.Status: { + const isSome = value.param2 != null; + if (isSome) { const bytes = textEncoder.encode(value.param2); const id = swift.memory.retain(bytes); i32Stack.push(bytes.length); i32Stack.push(id); - i32Stack.push((value.param1 | 0)); - i32Stack.push(value.param0 ? 1 : 0); - const cleanup = undefined; - return { caseId: ComplexResultValues.Tag.Status, cleanup }; - } - case ComplexResultValues.Tag.Coordinates: { - f64Stack.push(value.param2); - f64Stack.push(value.param1); - f64Stack.push(value.param0); - const cleanup = undefined; - return { caseId: ComplexResultValues.Tag.Coordinates, cleanup }; - } - case ComplexResultValues.Tag.Comprehensive: { - const bytes = textEncoder.encode(value.param8); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - const bytes1 = textEncoder.encode(value.param7); - const id1 = swift.memory.retain(bytes1); - i32Stack.push(bytes1.length); - i32Stack.push(id1); - const bytes2 = textEncoder.encode(value.param6); - const id2 = swift.memory.retain(bytes2); - i32Stack.push(bytes2.length); - i32Stack.push(id2); - f64Stack.push(value.param5); - f64Stack.push(value.param4); - i32Stack.push((value.param3 | 0)); - i32Stack.push((value.param2 | 0)); - i32Stack.push(value.param1 ? 1 : 0); - i32Stack.push(value.param0 ? 1 : 0); - const cleanup = undefined; - return { caseId: ComplexResultValues.Tag.Comprehensive, cleanup }; - } - case ComplexResultValues.Tag.Info: { - const cleanup = undefined; - return { caseId: ComplexResultValues.Tag.Info, cleanup }; - } - default: throw new Error("Unknown ComplexResultValues tag: " + String(enumTag)); + } else { + i32Stack.push(0); + i32Stack.push(0); + } + i32Stack.push(isSome ? 1 : 0); + const isSome1 = value.param1 != null; + i32Stack.push(isSome1 ? (value.param1 | 0) : 0); + i32Stack.push(isSome1 ? 1 : 0); + const isSome2 = value.param0 != null; + i32Stack.push(isSome2 ? (value.param0 ? 1 : 0) : 0); + i32Stack.push(isSome2 ? 1 : 0); + return APIOptionalResultValues.Tag.Status; } - }, - lift: (tag) => { - tag = tag | 0; - switch (tag) { - case ComplexResultValues.Tag.Success: { - const string = strStack.pop(); - return { tag: ComplexResultValues.Tag.Success, param0: string }; - } - case ComplexResultValues.Tag.Error: { - const int = i32Stack.pop(); + default: throw new Error("Unknown APIOptionalResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case APIOptionalResultValues.Tag.Success: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { const string = strStack.pop(); - return { tag: ComplexResultValues.Tag.Error, param0: string, param1: int }; + optional = string; + } else { + optional = null; } - case ComplexResultValues.Tag.Status: { - const string = strStack.pop(); - const int = i32Stack.pop(); + return { tag: APIOptionalResultValues.Tag.Success, param0: optional }; + } + case APIOptionalResultValues.Tag.Failure: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { const bool = i32Stack.pop() !== 0; - return { tag: ComplexResultValues.Tag.Status, param0: bool, param1: int, param2: string }; - } - case ComplexResultValues.Tag.Coordinates: { - const f64 = f64Stack.pop(); - const f641 = f64Stack.pop(); - const f642 = f64Stack.pop(); - return { tag: ComplexResultValues.Tag.Coordinates, param0: f642, param1: f641, param2: f64 }; + optional = bool; + } else { + optional = null; } - case ComplexResultValues.Tag.Comprehensive: { - const string = strStack.pop(); - const string1 = strStack.pop(); - const string2 = strStack.pop(); - const f64 = f64Stack.pop(); - const f641 = f64Stack.pop(); + const isSome1 = i32Stack.pop(); + let optional1; + if (isSome1) { const int = i32Stack.pop(); - const int1 = i32Stack.pop(); - const bool = i32Stack.pop() !== 0; - const bool1 = i32Stack.pop() !== 0; - return { tag: ComplexResultValues.Tag.Comprehensive, param0: bool1, param1: bool, param2: int1, param3: int, param4: f641, param5: f64, param6: string2, param7: string1, param8: string }; - } - case ComplexResultValues.Tag.Info: return { tag: ComplexResultValues.Tag.Info }; - default: throw new Error("Unknown ComplexResultValues tag returned from Swift: " + String(tag)); - } - } - }); - }; - const __bjs_createResultValuesHelpers = () => { - return () => ({ - lower: (value) => { - const enumTag = value.tag; - switch (enumTag) { - case ResultValues.Tag.Success: { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - const cleanup = undefined; - return { caseId: ResultValues.Tag.Success, cleanup }; - } - case ResultValues.Tag.Failure: { - i32Stack.push((value.param1 | 0)); - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - const cleanup = undefined; - return { caseId: ResultValues.Tag.Failure, cleanup }; - } - case ResultValues.Tag.Status: { - const bytes = textEncoder.encode(value.param2); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - i32Stack.push((value.param1 | 0)); - i32Stack.push(value.param0 ? 1 : 0); - const cleanup = undefined; - return { caseId: ResultValues.Tag.Status, cleanup }; + optional1 = int; + } else { + optional1 = null; } - default: throw new Error("Unknown ResultValues tag: " + String(enumTag)); + return { tag: APIOptionalResultValues.Tag.Failure, param0: optional1, param1: optional }; } - }, - lift: (tag) => { - tag = tag | 0; - switch (tag) { - case ResultValues.Tag.Success: { + case APIOptionalResultValues.Tag.Status: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { const string = strStack.pop(); - return { tag: ResultValues.Tag.Success, param0: string }; + optional = string; + } else { + optional = null; } - case ResultValues.Tag.Failure: { + const isSome1 = i32Stack.pop(); + let optional1; + if (isSome1) { const int = i32Stack.pop(); - const string = strStack.pop(); - return { tag: ResultValues.Tag.Failure, param0: string, param1: int }; + optional1 = int; + } else { + optional1 = null; } - case ResultValues.Tag.Status: { - const string = strStack.pop(); - const int = i32Stack.pop(); + const isSome2 = i32Stack.pop(); + let optional2; + if (isSome2) { const bool = i32Stack.pop() !== 0; - return { tag: ResultValues.Tag.Status, param0: bool, param1: int, param2: string }; + optional2 = bool; + } else { + optional2 = null; } - default: throw new Error("Unknown ResultValues tag returned from Swift: " + String(tag)); + return { tag: APIOptionalResultValues.Tag.Status, param0: optional2, param1: optional1, param2: optional }; } + default: throw new Error("Unknown APIOptionalResultValues tag returned from Swift: " + String(tag)); } - }); - }; - const __bjs_createNetworkingResultValuesHelpers = () => { - return () => ({ - lower: (value) => { - const enumTag = value.tag; - switch (enumTag) { - case NetworkingResultValues.Tag.Success: { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - const cleanup = undefined; - return { caseId: NetworkingResultValues.Tag.Success, cleanup }; - } - case NetworkingResultValues.Tag.Failure: { - i32Stack.push((value.param1 | 0)); - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - const cleanup = undefined; - return { caseId: NetworkingResultValues.Tag.Failure, cleanup }; - } - default: throw new Error("Unknown NetworkingResultValues tag: " + String(enumTag)); + } + }); + const __bjs_createTypedPayloadResultValuesHelpers = () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case TypedPayloadResultValues.Tag.Precision: { + f32Stack.push(Math.fround(value.param0)); + return TypedPayloadResultValues.Tag.Precision; } - }, - lift: (tag) => { - tag = tag | 0; - switch (tag) { - case NetworkingResultValues.Tag.Success: { - const string = strStack.pop(); - return { tag: NetworkingResultValues.Tag.Success, param0: string }; - } - case NetworkingResultValues.Tag.Failure: { - const int = i32Stack.pop(); - const string = strStack.pop(); - return { tag: NetworkingResultValues.Tag.Failure, param0: string, param1: int }; - } - default: throw new Error("Unknown NetworkingResultValues tag returned from Swift: " + String(tag)); + case TypedPayloadResultValues.Tag.Direction: { + i32Stack.push((value.param0 | 0)); + return TypedPayloadResultValues.Tag.Direction; } - } - }); - }; - const __bjs_createAPIOptionalResultValuesHelpers = () => { - return () => ({ - lower: (value) => { - const enumTag = value.tag; - switch (enumTag) { - case APIOptionalResultValues.Tag.Success: { - const isSome = value.param0 != null; - let id; - if (isSome) { - let bytes = textEncoder.encode(value.param0); - id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - } else { - i32Stack.push(0); - i32Stack.push(0); - } - i32Stack.push(isSome ? 1 : 0); - const cleanup = undefined; - return { caseId: APIOptionalResultValues.Tag.Success, cleanup }; - } - case APIOptionalResultValues.Tag.Failure: { - const isSome = value.param1 != null; - i32Stack.push(isSome ? (value.param1 ? 1 : 0) : 0); - i32Stack.push(isSome ? 1 : 0); - const isSome1 = value.param0 != null; - i32Stack.push(isSome1 ? (value.param0 | 0) : 0); - i32Stack.push(isSome1 ? 1 : 0); - const cleanup = undefined; - return { caseId: APIOptionalResultValues.Tag.Failure, cleanup }; - } - case APIOptionalResultValues.Tag.Status: { - const isSome = value.param2 != null; - let id; - if (isSome) { - let bytes = textEncoder.encode(value.param2); - id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - } else { - i32Stack.push(0); - i32Stack.push(0); - } - i32Stack.push(isSome ? 1 : 0); - const isSome1 = value.param1 != null; - i32Stack.push(isSome1 ? (value.param1 | 0) : 0); - i32Stack.push(isSome1 ? 1 : 0); - const isSome2 = value.param0 != null; - i32Stack.push(isSome2 ? (value.param0 ? 1 : 0) : 0); - i32Stack.push(isSome2 ? 1 : 0); - const cleanup = undefined; - return { caseId: APIOptionalResultValues.Tag.Status, cleanup }; - } - default: throw new Error("Unknown APIOptionalResultValues tag: " + String(enumTag)); - } - }, - lift: (tag) => { - tag = tag | 0; - switch (tag) { - case APIOptionalResultValues.Tag.Success: { - const isSome = i32Stack.pop(); - let optional; - if (isSome) { - const string = strStack.pop(); - optional = string; - } else { - optional = null; - } - return { tag: APIOptionalResultValues.Tag.Success, param0: optional }; - } - case APIOptionalResultValues.Tag.Failure: { - const isSome = i32Stack.pop(); - let optional; - if (isSome) { - const bool = i32Stack.pop() !== 0; - optional = bool; - } else { - optional = null; - } - const isSome1 = i32Stack.pop(); - let optional1; - if (isSome1) { - const int = i32Stack.pop(); - optional1 = int; - } else { - optional1 = null; - } - return { tag: APIOptionalResultValues.Tag.Failure, param0: optional1, param1: optional }; - } - case APIOptionalResultValues.Tag.Status: { - const isSome = i32Stack.pop(); - let optional; - if (isSome) { - const string = strStack.pop(); - optional = string; - } else { - optional = null; - } - const isSome1 = i32Stack.pop(); - let optional1; - if (isSome1) { - const int = i32Stack.pop(); - optional1 = int; - } else { - optional1 = null; - } - const isSome2 = i32Stack.pop(); - let optional2; - if (isSome2) { - const bool = i32Stack.pop() !== 0; - optional2 = bool; - } else { - optional2 = null; - } - return { tag: APIOptionalResultValues.Tag.Status, param0: optional2, param1: optional1, param2: optional }; - } - default: throw new Error("Unknown APIOptionalResultValues tag returned from Swift: " + String(tag)); + case TypedPayloadResultValues.Tag.OptPrecision: { + const isSome = value.param0 != null; + f32Stack.push(isSome ? Math.fround(value.param0) : 0.0); + i32Stack.push(isSome ? 1 : 0); + return TypedPayloadResultValues.Tag.OptPrecision; } + case TypedPayloadResultValues.Tag.OptDirection: { + const isSome = value.param0 != null; + i32Stack.push(isSome ? (value.param0 | 0) : 0); + i32Stack.push(isSome ? 1 : 0); + return TypedPayloadResultValues.Tag.OptDirection; + } + case TypedPayloadResultValues.Tag.Empty: { + return TypedPayloadResultValues.Tag.Empty; + } + default: throw new Error("Unknown TypedPayloadResultValues tag: " + String(enumTag)); } - }); - }; - const __bjs_createTypedPayloadResultValuesHelpers = () => { - return () => ({ - lower: (value) => { - const enumTag = value.tag; - switch (enumTag) { - case TypedPayloadResultValues.Tag.Precision: { - f32Stack.push(Math.fround(value.param0)); - const cleanup = undefined; - return { caseId: TypedPayloadResultValues.Tag.Precision, cleanup }; - } - case TypedPayloadResultValues.Tag.Direction: { - i32Stack.push((value.param0 | 0)); - const cleanup = undefined; - return { caseId: TypedPayloadResultValues.Tag.Direction, cleanup }; - } - case TypedPayloadResultValues.Tag.OptPrecision: { - const isSome = value.param0 != null; - f32Stack.push(isSome ? Math.fround(value.param0) : 0.0); - i32Stack.push(isSome ? 1 : 0); - const cleanup = undefined; - return { caseId: TypedPayloadResultValues.Tag.OptPrecision, cleanup }; - } - case TypedPayloadResultValues.Tag.OptDirection: { - const isSome = value.param0 != null; - i32Stack.push(isSome ? (value.param0 | 0) : 0); - i32Stack.push(isSome ? 1 : 0); - const cleanup = undefined; - return { caseId: TypedPayloadResultValues.Tag.OptDirection, cleanup }; - } - case TypedPayloadResultValues.Tag.Empty: { - const cleanup = undefined; - return { caseId: TypedPayloadResultValues.Tag.Empty, cleanup }; - } - default: throw new Error("Unknown TypedPayloadResultValues tag: " + String(enumTag)); + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case TypedPayloadResultValues.Tag.Precision: { + const rawValue = f32Stack.pop(); + return { tag: TypedPayloadResultValues.Tag.Precision, param0: rawValue }; + } + case TypedPayloadResultValues.Tag.Direction: { + const caseId = i32Stack.pop(); + return { tag: TypedPayloadResultValues.Tag.Direction, param0: caseId }; } - }, - lift: (tag) => { - tag = tag | 0; - switch (tag) { - case TypedPayloadResultValues.Tag.Precision: { + case TypedPayloadResultValues.Tag.OptPrecision: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { const rawValue = f32Stack.pop(); - return { tag: TypedPayloadResultValues.Tag.Precision, param0: rawValue }; + optional = rawValue; + } else { + optional = null; } - case TypedPayloadResultValues.Tag.Direction: { + return { tag: TypedPayloadResultValues.Tag.OptPrecision, param0: optional }; + } + case TypedPayloadResultValues.Tag.OptDirection: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { const caseId = i32Stack.pop(); - return { tag: TypedPayloadResultValues.Tag.Direction, param0: caseId }; + optional = caseId; + } else { + optional = null; } - case TypedPayloadResultValues.Tag.OptPrecision: { - const isSome = i32Stack.pop(); - let optional; - if (isSome) { - const rawValue = f32Stack.pop(); - optional = rawValue; - } else { - optional = null; - } - return { tag: TypedPayloadResultValues.Tag.OptPrecision, param0: optional }; + return { tag: TypedPayloadResultValues.Tag.OptDirection, param0: optional }; + } + case TypedPayloadResultValues.Tag.Empty: return { tag: TypedPayloadResultValues.Tag.Empty }; + default: throw new Error("Unknown TypedPayloadResultValues tag returned from Swift: " + String(tag)); + } + } + }); + const __bjs_createAllTypesResultValuesHelpers = () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case AllTypesResultValues.Tag.StructPayload: { + structHelpers.Point.lower(value.param0); + return AllTypesResultValues.Tag.StructPayload; + } + case AllTypesResultValues.Tag.ClassPayload: { + ptrStack.push(value.param0.pointer); + return AllTypesResultValues.Tag.ClassPayload; + } + case AllTypesResultValues.Tag.JsObjectPayload: { + const objId = swift.memory.retain(value.param0); + i32Stack.push(objId); + return AllTypesResultValues.Tag.JsObjectPayload; + } + case AllTypesResultValues.Tag.NestedEnum: { + const caseId = enumHelpers.APIResult.lower(value.param0); + i32Stack.push(caseId); + return AllTypesResultValues.Tag.NestedEnum; + } + case AllTypesResultValues.Tag.ArrayPayload: { + for (const elem of value.param0) { + i32Stack.push((elem | 0)); } - case TypedPayloadResultValues.Tag.OptDirection: { - const isSome = i32Stack.pop(); - let optional; - if (isSome) { - const caseId = i32Stack.pop(); - optional = caseId; - } else { - optional = null; - } - return { tag: TypedPayloadResultValues.Tag.OptDirection, param0: optional }; + i32Stack.push(value.param0.length); + return AllTypesResultValues.Tag.ArrayPayload; + } + case AllTypesResultValues.Tag.Empty: { + return AllTypesResultValues.Tag.Empty; + } + default: throw new Error("Unknown AllTypesResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case AllTypesResultValues.Tag.StructPayload: { + const struct = structHelpers.Point.lift(); + return { tag: AllTypesResultValues.Tag.StructPayload, param0: struct }; + } + case AllTypesResultValues.Tag.ClassPayload: { + const ptr = ptrStack.pop(); + const obj = _exports['User'].__construct(ptr); + return { tag: AllTypesResultValues.Tag.ClassPayload, param0: obj }; + } + case AllTypesResultValues.Tag.JsObjectPayload: { + const objId = i32Stack.pop(); + const obj = swift.memory.getObject(objId); + swift.memory.release(objId); + return { tag: AllTypesResultValues.Tag.JsObjectPayload, param0: obj }; + } + case AllTypesResultValues.Tag.NestedEnum: { + const enumValue = enumHelpers.APIResult.lift(i32Stack.pop()); + return { tag: AllTypesResultValues.Tag.NestedEnum, param0: enumValue }; + } + case AllTypesResultValues.Tag.ArrayPayload: { + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.pop(); + arrayResult.push(int); } - case TypedPayloadResultValues.Tag.Empty: return { tag: TypedPayloadResultValues.Tag.Empty }; - default: throw new Error("Unknown TypedPayloadResultValues tag returned from Swift: " + String(tag)); + arrayResult.reverse(); + return { tag: AllTypesResultValues.Tag.ArrayPayload, param0: arrayResult }; } + case AllTypesResultValues.Tag.Empty: return { tag: AllTypesResultValues.Tag.Empty }; + default: throw new Error("Unknown AllTypesResultValues tag returned from Swift: " + String(tag)); } - }); - }; - const __bjs_createAllTypesResultValuesHelpers = () => { - return () => ({ - lower: (value) => { - const enumTag = value.tag; - switch (enumTag) { - case AllTypesResultValues.Tag.StructPayload: { - const { cleanup: structCleanup } = structHelpers.Point.lower(value.param0); - const cleanup = () => { - if (structCleanup) { structCleanup(); } - }; - return { caseId: AllTypesResultValues.Tag.StructPayload, cleanup }; + } + }); + const __bjs_createOptionalAllTypesResultValuesHelpers = () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case OptionalAllTypesResultValues.Tag.OptStruct: { + const isSome = value.param0 != null; + if (isSome) { + structHelpers.Point.lower(value.param0); } - case AllTypesResultValues.Tag.ClassPayload: { + i32Stack.push(isSome ? 1 : 0); + return OptionalAllTypesResultValues.Tag.OptStruct; + } + case OptionalAllTypesResultValues.Tag.OptClass: { + const isSome = value.param0 != null; + if (isSome) { ptrStack.push(value.param0.pointer); - const cleanup = undefined; - return { caseId: AllTypesResultValues.Tag.ClassPayload, cleanup }; + } else { + ptrStack.push(0); } - case AllTypesResultValues.Tag.JsObjectPayload: { + i32Stack.push(isSome ? 1 : 0); + return OptionalAllTypesResultValues.Tag.OptClass; + } + case OptionalAllTypesResultValues.Tag.OptJSObject: { + const isSome = value.param0 != null; + if (isSome) { const objId = swift.memory.retain(value.param0); i32Stack.push(objId); - const cleanup = undefined; - return { caseId: AllTypesResultValues.Tag.JsObjectPayload, cleanup }; + } else { + i32Stack.push(0); } - case AllTypesResultValues.Tag.NestedEnum: { - const { caseId: caseId, cleanup: enumCleanup } = enumHelpers.APIResult.lower(value.param0); + i32Stack.push(isSome ? 1 : 0); + return OptionalAllTypesResultValues.Tag.OptJSObject; + } + case OptionalAllTypesResultValues.Tag.OptNestedEnum: { + const isSome = value.param0 != null; + if (isSome) { + const caseId = enumHelpers.APIResult.lower(value.param0); i32Stack.push(caseId); - const cleanup = () => { - if (enumCleanup) { enumCleanup(); } - }; - return { caseId: AllTypesResultValues.Tag.NestedEnum, cleanup }; + } else { + i32Stack.push(0); } - case AllTypesResultValues.Tag.ArrayPayload: { - const arrayCleanups = []; + i32Stack.push(isSome ? 1 : 0); + return OptionalAllTypesResultValues.Tag.OptNestedEnum; + } + case OptionalAllTypesResultValues.Tag.OptArray: { + const isSome = value.param0 != null; + if (isSome) { for (const elem of value.param0) { i32Stack.push((elem | 0)); } i32Stack.push(value.param0.length); - const cleanup = () => { - for (const cleanup of arrayCleanups) { cleanup(); } - }; - return { caseId: AllTypesResultValues.Tag.ArrayPayload, cleanup }; - } - case AllTypesResultValues.Tag.Empty: { - const cleanup = undefined; - return { caseId: AllTypesResultValues.Tag.Empty, cleanup }; } - default: throw new Error("Unknown AllTypesResultValues tag: " + String(enumTag)); + i32Stack.push(isSome ? 1 : 0); + return OptionalAllTypesResultValues.Tag.OptArray; } - }, - lift: (tag) => { - tag = tag | 0; - switch (tag) { - case AllTypesResultValues.Tag.StructPayload: { + case OptionalAllTypesResultValues.Tag.Empty: { + return OptionalAllTypesResultValues.Tag.Empty; + } + default: throw new Error("Unknown OptionalAllTypesResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case OptionalAllTypesResultValues.Tag.OptStruct: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { const struct = structHelpers.Point.lift(); - return { tag: AllTypesResultValues.Tag.StructPayload, param0: struct }; + optional = struct; + } else { + optional = null; } - case AllTypesResultValues.Tag.ClassPayload: { + return { tag: OptionalAllTypesResultValues.Tag.OptStruct, param0: optional }; + } + case OptionalAllTypesResultValues.Tag.OptClass: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { const ptr = ptrStack.pop(); const obj = _exports['User'].__construct(ptr); - return { tag: AllTypesResultValues.Tag.ClassPayload, param0: obj }; + optional = obj; + } else { + optional = null; } - case AllTypesResultValues.Tag.JsObjectPayload: { + return { tag: OptionalAllTypesResultValues.Tag.OptClass, param0: optional }; + } + case OptionalAllTypesResultValues.Tag.OptJSObject: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { const objId = i32Stack.pop(); const obj = swift.memory.getObject(objId); swift.memory.release(objId); - return { tag: AllTypesResultValues.Tag.JsObjectPayload, param0: obj }; + optional = obj; + } else { + optional = null; } - case AllTypesResultValues.Tag.NestedEnum: { - const enumValue = enumHelpers.APIResult.lift(i32Stack.pop(), ); - return { tag: AllTypesResultValues.Tag.NestedEnum, param0: enumValue }; + return { tag: OptionalAllTypesResultValues.Tag.OptJSObject, param0: optional }; + } + case OptionalAllTypesResultValues.Tag.OptNestedEnum: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const caseId = i32Stack.pop(); + optional = enumHelpers.APIResult.lift(caseId); + } else { + optional = null; } - case AllTypesResultValues.Tag.ArrayPayload: { + return { tag: OptionalAllTypesResultValues.Tag.OptNestedEnum, param0: optional }; + } + case OptionalAllTypesResultValues.Tag.OptArray: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { const arrayLen = i32Stack.pop(); const arrayResult = []; for (let i = 0; i < arrayLen; i++) { @@ -678,173 +750,17 @@ export async function createInstantiator(options, swift) { arrayResult.push(int); } arrayResult.reverse(); - return { tag: AllTypesResultValues.Tag.ArrayPayload, param0: arrayResult }; - } - case AllTypesResultValues.Tag.Empty: return { tag: AllTypesResultValues.Tag.Empty }; - default: throw new Error("Unknown AllTypesResultValues tag returned from Swift: " + String(tag)); - } - } - }); - }; - const __bjs_createOptionalAllTypesResultValuesHelpers = () => { - return () => ({ - lower: (value) => { - const enumTag = value.tag; - switch (enumTag) { - case OptionalAllTypesResultValues.Tag.OptStruct: { - const isSome = value.param0 != null; - let nestedCleanup; - if (isSome) { - const structResult = structHelpers.Point.lower(value.param0); - nestedCleanup = structResult.cleanup; - } - i32Stack.push(isSome ? 1 : 0); - const cleanup = () => { - if (nestedCleanup) { nestedCleanup(); } - }; - return { caseId: OptionalAllTypesResultValues.Tag.OptStruct, cleanup }; - } - case OptionalAllTypesResultValues.Tag.OptClass: { - const isSome = value.param0 != null; - if (isSome) { - ptrStack.push(value.param0.pointer); - } else { - ptrStack.push(0); - } - i32Stack.push(isSome ? 1 : 0); - const cleanup = undefined; - return { caseId: OptionalAllTypesResultValues.Tag.OptClass, cleanup }; - } - case OptionalAllTypesResultValues.Tag.OptJSObject: { - const isSome = value.param0 != null; - let id; - if (isSome) { - id = swift.memory.retain(value.param0); - i32Stack.push(id); - } else { - id = undefined; - i32Stack.push(0); - } - i32Stack.push(isSome ? 1 : 0); - const cleanup = undefined; - return { caseId: OptionalAllTypesResultValues.Tag.OptJSObject, cleanup }; - } - case OptionalAllTypesResultValues.Tag.OptNestedEnum: { - const isSome = value.param0 != null; - let enumCaseId, enumCleanup; - if (isSome) { - const enumResult = enumHelpers.APIResult.lower(value.param0); - enumCaseId = enumResult.caseId; - enumCleanup = enumResult.cleanup; - i32Stack.push(enumCaseId); - } else { - i32Stack.push(0); - } - i32Stack.push(isSome ? 1 : 0); - const cleanup = () => { - if (enumCleanup) { enumCleanup(); } - }; - return { caseId: OptionalAllTypesResultValues.Tag.OptNestedEnum, cleanup }; - } - case OptionalAllTypesResultValues.Tag.OptArray: { - const isSome = value.param0 != null; - let arrCleanup; - if (isSome) { - const arrayCleanups = []; - for (const elem of value.param0) { - i32Stack.push((elem | 0)); - } - i32Stack.push(value.param0.length); - arrCleanup = () => { - for (const cleanup of arrayCleanups) { cleanup(); } - }; - } - i32Stack.push(isSome ? 1 : 0); - const cleanup = () => { - if (arrCleanup) { arrCleanup(); } - }; - return { caseId: OptionalAllTypesResultValues.Tag.OptArray, cleanup }; - } - case OptionalAllTypesResultValues.Tag.Empty: { - const cleanup = undefined; - return { caseId: OptionalAllTypesResultValues.Tag.Empty, cleanup }; - } - default: throw new Error("Unknown OptionalAllTypesResultValues tag: " + String(enumTag)); - } - }, - lift: (tag) => { - tag = tag | 0; - switch (tag) { - case OptionalAllTypesResultValues.Tag.OptStruct: { - const isSome = i32Stack.pop(); - let optional; - if (isSome) { - const struct = structHelpers.Point.lift(); - optional = struct; - } else { - optional = null; - } - return { tag: OptionalAllTypesResultValues.Tag.OptStruct, param0: optional }; - } - case OptionalAllTypesResultValues.Tag.OptClass: { - const isSome = i32Stack.pop(); - let optional; - if (isSome) { - const ptr = ptrStack.pop(); - const obj = _exports['User'].__construct(ptr); - optional = obj; - } else { - optional = null; - } - return { tag: OptionalAllTypesResultValues.Tag.OptClass, param0: optional }; - } - case OptionalAllTypesResultValues.Tag.OptJSObject: { - const isSome = i32Stack.pop(); - let optional; - if (isSome) { - const objId = i32Stack.pop(); - const obj = swift.memory.getObject(objId); - swift.memory.release(objId); - optional = obj; - } else { - optional = null; - } - return { tag: OptionalAllTypesResultValues.Tag.OptJSObject, param0: optional }; - } - case OptionalAllTypesResultValues.Tag.OptNestedEnum: { - const isSome = i32Stack.pop(); - let optional; - if (isSome) { - const caseId = i32Stack.pop(); - optional = enumHelpers.APIResult.lift(caseId); - } else { - optional = null; - } - return { tag: OptionalAllTypesResultValues.Tag.OptNestedEnum, param0: optional }; - } - case OptionalAllTypesResultValues.Tag.OptArray: { - const isSome = i32Stack.pop(); - let optional; - if (isSome) { - const arrayLen = i32Stack.pop(); - const arrayResult = []; - for (let i = 0; i < arrayLen; i++) { - const int = i32Stack.pop(); - arrayResult.push(int); - } - arrayResult.reverse(); - optional = arrayResult; - } else { - optional = null; - } - return { tag: OptionalAllTypesResultValues.Tag.OptArray, param0: optional }; + optional = arrayResult; + } else { + optional = null; } - case OptionalAllTypesResultValues.Tag.Empty: return { tag: OptionalAllTypesResultValues.Tag.Empty }; - default: throw new Error("Unknown OptionalAllTypesResultValues tag returned from Swift: " + String(tag)); + return { tag: OptionalAllTypesResultValues.Tag.OptArray, param0: optional }; } + case OptionalAllTypesResultValues.Tag.Empty: return { tag: OptionalAllTypesResultValues.Tag.Empty }; + default: throw new Error("Unknown OptionalAllTypesResultValues tag returned from Swift: " + String(tag)); } - }); - }; + } + }); return { /** @@ -892,8 +808,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -910,22 +825,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_struct_lower_Point"] = function(objectId) { - const { cleanup: cleanup } = structHelpers.Point.lower(swift.memory.getObject(objectId)); - if (cleanup) { - return tmpStructCleanups.push(cleanup); - } - return 0; + structHelpers.Point.lower(swift.memory.getObject(objectId)); } bjs["swift_js_struct_lift_Point"] = function() { const value = structHelpers.Point.lift(); @@ -1067,39 +968,38 @@ export async function createInstantiator(options, swift) { } } - const PointHelpers = __bjs_createPointHelpers()(); + const PointHelpers = __bjs_createPointHelpers(); structHelpers.Point = PointHelpers; - const APIResultHelpers = __bjs_createAPIResultValuesHelpers()(); + const APIResultHelpers = __bjs_createAPIResultValuesHelpers(); enumHelpers.APIResult = APIResultHelpers; - const ComplexResultHelpers = __bjs_createComplexResultValuesHelpers()(); + const ComplexResultHelpers = __bjs_createComplexResultValuesHelpers(); enumHelpers.ComplexResult = ComplexResultHelpers; - const ResultHelpers = __bjs_createResultValuesHelpers()(); + const ResultHelpers = __bjs_createResultValuesHelpers(); enumHelpers.Result = ResultHelpers; - const NetworkingResultHelpers = __bjs_createNetworkingResultValuesHelpers()(); + const NetworkingResultHelpers = __bjs_createNetworkingResultValuesHelpers(); enumHelpers.NetworkingResult = NetworkingResultHelpers; - const APIOptionalResultHelpers = __bjs_createAPIOptionalResultValuesHelpers()(); + const APIOptionalResultHelpers = __bjs_createAPIOptionalResultValuesHelpers(); enumHelpers.APIOptionalResult = APIOptionalResultHelpers; - const TypedPayloadResultHelpers = __bjs_createTypedPayloadResultValuesHelpers()(); + const TypedPayloadResultHelpers = __bjs_createTypedPayloadResultValuesHelpers(); enumHelpers.TypedPayloadResult = TypedPayloadResultHelpers; - const AllTypesResultHelpers = __bjs_createAllTypesResultValuesHelpers()(); + const AllTypesResultHelpers = __bjs_createAllTypesResultValuesHelpers(); enumHelpers.AllTypesResult = AllTypesResultHelpers; - const OptionalAllTypesResultHelpers = __bjs_createOptionalAllTypesResultValuesHelpers()(); + const OptionalAllTypesResultHelpers = __bjs_createOptionalAllTypesResultValuesHelpers(); enumHelpers.OptionalAllTypesResult = OptionalAllTypesResultHelpers; const exports = { User, handle: function bjs_handle(result) { - const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.APIResult.lower(result); + const resultCaseId = enumHelpers.APIResult.lower(result); instance.exports.bjs_handle(resultCaseId); - if (resultCleanup) { resultCleanup(); } }, getResult: function bjs_getResult() { instance.exports.bjs_getResult(); @@ -1107,36 +1007,28 @@ export async function createInstantiator(options, swift) { return ret; }, roundtripAPIResult: function bjs_roundtripAPIResult(result) { - const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.APIResult.lower(result); + const resultCaseId = enumHelpers.APIResult.lower(result); instance.exports.bjs_roundtripAPIResult(resultCaseId); const ret = enumHelpers.APIResult.lift(i32Stack.pop()); - if (resultCleanup) { resultCleanup(); } return ret; }, roundTripOptionalAPIResult: function bjs_roundTripOptionalAPIResult(result) { const isSome = result != null; - let resultCaseId, resultCleanup; + let result1; if (isSome) { - const enumResult = enumHelpers.APIResult.lower(result); - resultCaseId = enumResult.caseId; - resultCleanup = enumResult.cleanup; - } - instance.exports.bjs_roundTripOptionalAPIResult(+isSome, isSome ? resultCaseId : 0); - const tag = i32Stack.pop(); - const isNull = (tag === -1); - let optResult; - if (isNull) { - optResult = null; + const resultCaseId = enumHelpers.APIResult.lower(result); + result1 = resultCaseId; } else { - optResult = enumHelpers.APIResult.lift(tag); + result1 = 0; } - if (resultCleanup) { resultCleanup(); } + instance.exports.bjs_roundTripOptionalAPIResult(+isSome, result1); + const tag = i32Stack.pop(); + const optResult = tag === -1 ? null : enumHelpers.APIResult.lift(tag); return optResult; }, handleComplex: function bjs_handleComplex(result) { - const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.ComplexResult.lower(result); + const resultCaseId = enumHelpers.ComplexResult.lower(result); instance.exports.bjs_handleComplex(resultCaseId); - if (resultCleanup) { resultCleanup(); } }, getComplexResult: function bjs_getComplexResult() { instance.exports.bjs_getComplexResult(); @@ -1144,199 +1036,147 @@ export async function createInstantiator(options, swift) { return ret; }, roundtripComplexResult: function bjs_roundtripComplexResult(result) { - const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.ComplexResult.lower(result); + const resultCaseId = enumHelpers.ComplexResult.lower(result); instance.exports.bjs_roundtripComplexResult(resultCaseId); const ret = enumHelpers.ComplexResult.lift(i32Stack.pop()); - if (resultCleanup) { resultCleanup(); } return ret; }, roundTripOptionalComplexResult: function bjs_roundTripOptionalComplexResult(result) { const isSome = result != null; - let resultCaseId, resultCleanup; + let result1; if (isSome) { - const enumResult = enumHelpers.ComplexResult.lower(result); - resultCaseId = enumResult.caseId; - resultCleanup = enumResult.cleanup; - } - instance.exports.bjs_roundTripOptionalComplexResult(+isSome, isSome ? resultCaseId : 0); - const tag = i32Stack.pop(); - const isNull = (tag === -1); - let optResult; - if (isNull) { - optResult = null; + const resultCaseId = enumHelpers.ComplexResult.lower(result); + result1 = resultCaseId; } else { - optResult = enumHelpers.ComplexResult.lift(tag); + result1 = 0; } - if (resultCleanup) { resultCleanup(); } + instance.exports.bjs_roundTripOptionalComplexResult(+isSome, result1); + const tag = i32Stack.pop(); + const optResult = tag === -1 ? null : enumHelpers.ComplexResult.lift(tag); return optResult; }, roundTripOptionalUtilitiesResult: function bjs_roundTripOptionalUtilitiesResult(result) { const isSome = result != null; - let resultCaseId, resultCleanup; + let result1; if (isSome) { - const enumResult = enumHelpers.Result.lower(result); - resultCaseId = enumResult.caseId; - resultCleanup = enumResult.cleanup; - } - instance.exports.bjs_roundTripOptionalUtilitiesResult(+isSome, isSome ? resultCaseId : 0); - const tag = i32Stack.pop(); - const isNull = (tag === -1); - let optResult; - if (isNull) { - optResult = null; + const resultCaseId = enumHelpers.Result.lower(result); + result1 = resultCaseId; } else { - optResult = enumHelpers.Result.lift(tag); + result1 = 0; } - if (resultCleanup) { resultCleanup(); } + instance.exports.bjs_roundTripOptionalUtilitiesResult(+isSome, result1); + const tag = i32Stack.pop(); + const optResult = tag === -1 ? null : enumHelpers.Result.lift(tag); return optResult; }, roundTripOptionalNetworkingResult: function bjs_roundTripOptionalNetworkingResult(result) { const isSome = result != null; - let resultCaseId, resultCleanup; + let result1; if (isSome) { - const enumResult = enumHelpers.NetworkingResult.lower(result); - resultCaseId = enumResult.caseId; - resultCleanup = enumResult.cleanup; - } - instance.exports.bjs_roundTripOptionalNetworkingResult(+isSome, isSome ? resultCaseId : 0); - const tag = i32Stack.pop(); - const isNull = (tag === -1); - let optResult; - if (isNull) { - optResult = null; + const resultCaseId = enumHelpers.NetworkingResult.lower(result); + result1 = resultCaseId; } else { - optResult = enumHelpers.NetworkingResult.lift(tag); + result1 = 0; } - if (resultCleanup) { resultCleanup(); } + instance.exports.bjs_roundTripOptionalNetworkingResult(+isSome, result1); + const tag = i32Stack.pop(); + const optResult = tag === -1 ? null : enumHelpers.NetworkingResult.lift(tag); return optResult; }, roundTripOptionalAPIOptionalResult: function bjs_roundTripOptionalAPIOptionalResult(result) { const isSome = result != null; - let resultCaseId, resultCleanup; + let result1; if (isSome) { - const enumResult = enumHelpers.APIOptionalResult.lower(result); - resultCaseId = enumResult.caseId; - resultCleanup = enumResult.cleanup; - } - instance.exports.bjs_roundTripOptionalAPIOptionalResult(+isSome, isSome ? resultCaseId : 0); - const tag = i32Stack.pop(); - const isNull = (tag === -1); - let optResult; - if (isNull) { - optResult = null; + const resultCaseId = enumHelpers.APIOptionalResult.lower(result); + result1 = resultCaseId; } else { - optResult = enumHelpers.APIOptionalResult.lift(tag); + result1 = 0; } - if (resultCleanup) { resultCleanup(); } + instance.exports.bjs_roundTripOptionalAPIOptionalResult(+isSome, result1); + const tag = i32Stack.pop(); + const optResult = tag === -1 ? null : enumHelpers.APIOptionalResult.lift(tag); return optResult; }, compareAPIResults: function bjs_compareAPIResults(result1, result2) { const isSome = result1 != null; - let result1CaseId, result1Cleanup; + let result; if (isSome) { - const enumResult = enumHelpers.APIOptionalResult.lower(result1); - result1CaseId = enumResult.caseId; - result1Cleanup = enumResult.cleanup; + const result1CaseId = enumHelpers.APIOptionalResult.lower(result1); + result = result1CaseId; + } else { + result = 0; } const isSome1 = result2 != null; - let result2CaseId, result2Cleanup; + let result3; if (isSome1) { - const enumResult1 = enumHelpers.APIOptionalResult.lower(result2); - result2CaseId = enumResult1.caseId; - result2Cleanup = enumResult1.cleanup; - } - instance.exports.bjs_compareAPIResults(+isSome, isSome ? result1CaseId : 0, +isSome1, isSome1 ? result2CaseId : 0); - const tag = i32Stack.pop(); - const isNull = (tag === -1); - let optResult; - if (isNull) { - optResult = null; + const result2CaseId = enumHelpers.APIOptionalResult.lower(result2); + result3 = result2CaseId; } else { - optResult = enumHelpers.APIOptionalResult.lift(tag); + result3 = 0; } - if (result1Cleanup) { result1Cleanup(); } - if (result2Cleanup) { result2Cleanup(); } + instance.exports.bjs_compareAPIResults(+isSome, result, +isSome1, result3); + const tag = i32Stack.pop(); + const optResult = tag === -1 ? null : enumHelpers.APIOptionalResult.lift(tag); return optResult; }, roundTripTypedPayloadResult: function bjs_roundTripTypedPayloadResult(result) { - const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.TypedPayloadResult.lower(result); + const resultCaseId = enumHelpers.TypedPayloadResult.lower(result); instance.exports.bjs_roundTripTypedPayloadResult(resultCaseId); const ret = enumHelpers.TypedPayloadResult.lift(i32Stack.pop()); - if (resultCleanup) { resultCleanup(); } return ret; }, roundTripOptionalTypedPayloadResult: function bjs_roundTripOptionalTypedPayloadResult(result) { const isSome = result != null; - let resultCaseId, resultCleanup; + let result1; if (isSome) { - const enumResult = enumHelpers.TypedPayloadResult.lower(result); - resultCaseId = enumResult.caseId; - resultCleanup = enumResult.cleanup; - } - instance.exports.bjs_roundTripOptionalTypedPayloadResult(+isSome, isSome ? resultCaseId : 0); - const tag = i32Stack.pop(); - const isNull = (tag === -1); - let optResult; - if (isNull) { - optResult = null; + const resultCaseId = enumHelpers.TypedPayloadResult.lower(result); + result1 = resultCaseId; } else { - optResult = enumHelpers.TypedPayloadResult.lift(tag); + result1 = 0; } - if (resultCleanup) { resultCleanup(); } + instance.exports.bjs_roundTripOptionalTypedPayloadResult(+isSome, result1); + const tag = i32Stack.pop(); + const optResult = tag === -1 ? null : enumHelpers.TypedPayloadResult.lift(tag); return optResult; }, roundTripAllTypesResult: function bjs_roundTripAllTypesResult(result) { - const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.AllTypesResult.lower(result); + const resultCaseId = enumHelpers.AllTypesResult.lower(result); instance.exports.bjs_roundTripAllTypesResult(resultCaseId); const ret = enumHelpers.AllTypesResult.lift(i32Stack.pop()); - if (resultCleanup) { resultCleanup(); } return ret; }, roundTripOptionalAllTypesResult: function bjs_roundTripOptionalAllTypesResult(result) { const isSome = result != null; - let resultCaseId, resultCleanup; + let result1; if (isSome) { - const enumResult = enumHelpers.AllTypesResult.lower(result); - resultCaseId = enumResult.caseId; - resultCleanup = enumResult.cleanup; - } - instance.exports.bjs_roundTripOptionalAllTypesResult(+isSome, isSome ? resultCaseId : 0); - const tag = i32Stack.pop(); - const isNull = (tag === -1); - let optResult; - if (isNull) { - optResult = null; + const resultCaseId = enumHelpers.AllTypesResult.lower(result); + result1 = resultCaseId; } else { - optResult = enumHelpers.AllTypesResult.lift(tag); + result1 = 0; } - if (resultCleanup) { resultCleanup(); } + instance.exports.bjs_roundTripOptionalAllTypesResult(+isSome, result1); + const tag = i32Stack.pop(); + const optResult = tag === -1 ? null : enumHelpers.AllTypesResult.lift(tag); return optResult; }, roundTripOptionalPayloadResult: function bjs_roundTripOptionalPayloadResult(result) { - const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.OptionalAllTypesResult.lower(result); + const resultCaseId = enumHelpers.OptionalAllTypesResult.lower(result); instance.exports.bjs_roundTripOptionalPayloadResult(resultCaseId); const ret = enumHelpers.OptionalAllTypesResult.lift(i32Stack.pop()); - if (resultCleanup) { resultCleanup(); } return ret; }, roundTripOptionalPayloadResultOpt: function bjs_roundTripOptionalPayloadResultOpt(result) { const isSome = result != null; - let resultCaseId, resultCleanup; + let result1; if (isSome) { - const enumResult = enumHelpers.OptionalAllTypesResult.lower(result); - resultCaseId = enumResult.caseId; - resultCleanup = enumResult.cleanup; - } - instance.exports.bjs_roundTripOptionalPayloadResultOpt(+isSome, isSome ? resultCaseId : 0); - const tag = i32Stack.pop(); - const isNull = (tag === -1); - let optResult; - if (isNull) { - optResult = null; + const resultCaseId = enumHelpers.OptionalAllTypesResult.lower(result); + result1 = resultCaseId; } else { - optResult = enumHelpers.OptionalAllTypesResult.lift(tag); + result1 = 0; } - if (resultCleanup) { resultCleanup(); } + instance.exports.bjs_roundTripOptionalPayloadResultOpt(+isSome, result1); + const tag = i32Stack.pop(); + const optResult = tag === -1 ? null : enumHelpers.OptionalAllTypesResult.lift(tag); return optResult; }, APIResult: APIResultValues, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js index 72d78dbe0..886fbbe94 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js @@ -47,7 +47,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -100,8 +99,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -118,16 +116,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js index 392788ef6..47390311a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js @@ -67,7 +67,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -120,8 +119,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -138,16 +136,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js index 0a2826a5e..8a4d7fbfb 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js @@ -48,7 +48,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -101,8 +100,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -119,16 +117,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js index b1ee0538f..abce38bac 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js @@ -98,7 +98,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -152,8 +151,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -170,16 +168,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -316,12 +304,18 @@ export async function createInstantiator(options, swift) { }, roundTripOptionalTheme: function bjs_roundTripOptionalTheme(input) { const isSome = input != null; - let inputId, inputBytes; + let result; + let result1; if (isSome) { - inputBytes = textEncoder.encode(input); - inputId = swift.memory.retain(inputBytes); + const inputBytes = textEncoder.encode(input); + const inputId = swift.memory.retain(inputBytes); + result = inputId; + result1 = inputBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_roundTripOptionalTheme(+isSome, isSome ? inputId : 0, isSome ? inputBytes.length : 0); + instance.exports.bjs_roundTripOptionalTheme(+isSome, result, result1); const optResult = tmpRetString; tmpRetString = undefined; return optResult; @@ -339,12 +333,18 @@ export async function createInstantiator(options, swift) { }, roundTripOptionalTSTheme: function bjs_roundTripOptionalTSTheme(input) { const isSome = input != null; - let inputId, inputBytes; + let result; + let result1; if (isSome) { - inputBytes = textEncoder.encode(input); - inputId = swift.memory.retain(inputBytes); + const inputBytes = textEncoder.encode(input); + const inputId = swift.memory.retain(inputBytes); + result = inputId; + result1 = inputBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_roundTripOptionalTSTheme(+isSome, isSome ? inputId : 0, isSome ? inputBytes.length : 0); + instance.exports.bjs_roundTripOptionalTSTheme(+isSome, result, result1); const optResult = tmpRetString; tmpRetString = undefined; return optResult; @@ -362,12 +362,18 @@ export async function createInstantiator(options, swift) { }, roundTripOptionalFeatureFlag: function bjs_roundTripOptionalFeatureFlag(input) { const isSome = input != null; - let inputId, inputBytes; + let result; + let result1; if (isSome) { - inputBytes = textEncoder.encode(input); - inputId = swift.memory.retain(inputBytes); + const inputBytes = textEncoder.encode(input); + const inputId = swift.memory.retain(inputBytes); + result = inputId; + result1 = inputBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_roundTripOptionalFeatureFlag(+isSome, isSome ? inputId : 0, isSome ? inputBytes.length : 0); + instance.exports.bjs_roundTripOptionalFeatureFlag(+isSome, result, result1); const optResult = tmpRetString; tmpRetString = undefined; return optResult; @@ -479,7 +485,7 @@ export async function createInstantiator(options, swift) { }, roundTripOptionalPrecision: function bjs_roundTripOptionalPrecision(input) { const isSome = input != null; - instance.exports.bjs_roundTripOptionalPrecision(+isSome, isSome ? input : 0); + instance.exports.bjs_roundTripOptionalPrecision(+isSome, isSome ? input : 0.0); const optResult = tmpRetOptionalFloat; tmpRetOptionalFloat = undefined; return optResult; @@ -493,7 +499,7 @@ export async function createInstantiator(options, swift) { }, roundTripOptionalRatio: function bjs_roundTripOptionalRatio(input) { const isSome = input != null; - instance.exports.bjs_roundTripOptionalRatio(+isSome, isSome ? input : 0); + instance.exports.bjs_roundTripOptionalRatio(+isSome, isSome ? input : 0.0); const optResult = tmpRetOptionalDouble; tmpRetOptionalDouble = undefined; return optResult; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js index 6f6bf9531..468acfa36 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -77,8 +76,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -95,16 +93,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js index 9d57a04d3..96270b3c6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -76,8 +75,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -94,16 +92,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js index 7c946a716..fb057e57c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -77,8 +76,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -95,16 +93,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -207,7 +195,6 @@ export async function createInstantiator(options, swift) { } arrayResult.reverse(); let ret = imports.roundtrip(arrayResult); - const arrayCleanups = []; for (const elem of ret) { i32Stack.push((elem | 0)); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js index 5d724202b..a37497a8b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js @@ -23,62 +23,61 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; let _exports = null; let bjs = null; - const __bjs_createFooContainerHelpers = () => { - return () => ({ - lower: (value) => { - let id; - if (value.foo != null) { - id = swift.memory.retain(value.foo); - } else { - id = undefined; - } - i32Stack.push(id !== undefined ? id : 0); - const isSome = value.optionalFoo != null; + const __bjs_createFooContainerHelpers = () => ({ + lower: (value) => { + let id; + if (value.foo != null) { + id = swift.memory.retain(value.foo); + } else { + id = undefined; + } + i32Stack.push(id !== undefined ? id : 0); + const isSome = value.optionalFoo != null; + if (isSome) { let id1; - if (isSome) { + if (value.optionalFoo != null) { id1 = swift.memory.retain(value.optionalFoo); - i32Stack.push(id1); } else { id1 = undefined; - i32Stack.push(0); - } - i32Stack.push(isSome ? 1 : 0); - return { cleanup: undefined }; - }, - lift: () => { - const isSome = i32Stack.pop(); - let optional; - if (isSome) { - const objectId = i32Stack.pop(); - let value; - if (objectId !== 0) { - value = swift.memory.getObject(objectId); - swift.memory.release(objectId); - } else { - value = null; - } - optional = value; - } else { - optional = null; } - const objectId1 = i32Stack.pop(); - let value1; - if (objectId1 !== 0) { - value1 = swift.memory.getObject(objectId1); - swift.memory.release(objectId1); + i32Stack.push(id1 !== undefined ? id1 : 0); + } else { + i32Stack.push(0); + } + i32Stack.push(isSome ? 1 : 0); + }, + lift: () => { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const objectId = i32Stack.pop(); + let value; + if (objectId !== 0) { + value = swift.memory.getObject(objectId); + swift.memory.release(objectId); } else { - value1 = null; + value = null; } - return { foo: value1, optionalFoo: optional }; - } - }); - }; + optional = value; + } else { + optional = null; + } + const objectId1 = i32Stack.pop(); + let value1; + if (objectId1 !== 0) { + value1 = swift.memory.getObject(objectId1); + swift.memory.release(objectId1); + } else { + value1 = null; + } + return { foo: value1, optionalFoo: optional }; + } + }); return { /** @@ -127,8 +126,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -145,22 +143,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_struct_lower_FooContainer"] = function(objectId) { - const { cleanup: cleanup } = structHelpers.FooContainer.lower(swift.memory.getObject(objectId)); - if (cleanup) { - return tmpStructCleanups.push(cleanup); - } - return 0; + structHelpers.FooContainer.lower(swift.memory.getObject(objectId)); } bjs["swift_js_struct_lift_FooContainer"] = function() { const value = structHelpers.FooContainer.lift(); @@ -278,7 +262,7 @@ export async function createInstantiator(options, swift) { /** @param {WebAssembly.Instance} instance */ createExports: (instance) => { const js = swift.memory.heap; - const FooContainerHelpers = __bjs_createFooContainerHelpers()(); + const FooContainerHelpers = __bjs_createFooContainerHelpers(); structHelpers.FooContainer = FooContainerHelpers; const exports = { @@ -295,7 +279,6 @@ export async function createInstantiator(options, swift) { return ret1; }, processFooArray: function bjs_processFooArray(foos) { - const arrayCleanups = []; for (const elem of foos) { const objId = swift.memory.retain(elem); i32Stack.push(objId); @@ -311,11 +294,9 @@ export async function createInstantiator(options, swift) { arrayResult.push(obj); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, processOptionalFooArray: function bjs_processOptionalFooArray(foos) { - const arrayCleanups = []; for (const elem of foos) { const isSome = elem != null ? 1 : 0; if (isSome) { @@ -344,14 +325,12 @@ export async function createInstantiator(options, swift) { arrayResult.push(optValue); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, roundtripFooContainer: function bjs_roundtripFooContainer(container) { - const { cleanup: cleanup } = structHelpers.FooContainer.lower(container); + structHelpers.FooContainer.lower(container); instance.exports.bjs_roundtripFooContainer(); const structValue = structHelpers.FooContainer.lift(); - if (cleanup) { cleanup(); } return structValue; }, }; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js index 54a0f2018..1d29d84e7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -77,8 +76,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -95,16 +93,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js index a192a1a8b..d26f812e7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -77,8 +76,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -95,16 +93,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js index 1166d1f62..5a10a5e0f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -77,8 +76,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -95,16 +93,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js index d45efc771..3a591919d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -166,8 +165,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -184,16 +182,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -319,7 +307,6 @@ export async function createInstantiator(options, swift) { } arrayResult.reverse(); let ret = imports.jsEchoJSValueArray(arrayResult); - const arrayCleanups = []; for (const elem of ret) { const [elemKind, elemPayload1, elemPayload2] = __bjs_jsValueLower(elem); i32Stack.push(elemKind); @@ -370,15 +357,39 @@ export async function createInstantiator(options, swift) { constructor(value, optionalValue) { const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); const isSome = optionalValue != null; - const [optionalValueKind, optionalValuePayload1, optionalValuePayload2] = __bjs_jsValueLower(optionalValue); - const ret = instance.exports.bjs_JSValueHolder_init(valueKind, valuePayload1, valuePayload2, +isSome, optionalValueKind, optionalValuePayload1, optionalValuePayload2); + let result; + let result1; + let result2; + if (isSome) { + const [optionalValueKind, optionalValuePayload1, optionalValuePayload2] = __bjs_jsValueLower(optionalValue); + result = optionalValueKind; + result1 = optionalValuePayload1; + result2 = optionalValuePayload2; + } else { + result = 0; + result1 = 0; + result2 = 0.0; + } + const ret = instance.exports.bjs_JSValueHolder_init(valueKind, valuePayload1, valuePayload2, +isSome, result, result1, result2); return JSValueHolder.__construct(ret); } update(value, optionalValue) { const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); const isSome = optionalValue != null; - const [optionalValueKind, optionalValuePayload1, optionalValuePayload2] = __bjs_jsValueLower(optionalValue); - instance.exports.bjs_JSValueHolder_update(this.pointer, valueKind, valuePayload1, valuePayload2, +isSome, optionalValueKind, optionalValuePayload1, optionalValuePayload2); + let result; + let result1; + let result2; + if (isSome) { + const [optionalValueKind, optionalValuePayload1, optionalValuePayload2] = __bjs_jsValueLower(optionalValue); + result = optionalValueKind; + result1 = optionalValuePayload1; + result2 = optionalValuePayload2; + } else { + result = 0; + result1 = 0; + result2 = 0.0; + } + instance.exports.bjs_JSValueHolder_update(this.pointer, valueKind, valuePayload1, valuePayload2, +isSome, result, result1, result2); } echo(value) { const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); @@ -391,8 +402,20 @@ export async function createInstantiator(options, swift) { } echoOptional(value) { const isSome = value != null; - const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); - instance.exports.bjs_JSValueHolder_echoOptional(this.pointer, +isSome, valueKind, valuePayload1, valuePayload2); + let result; + let result1; + let result2; + if (isSome) { + const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); + result = valueKind; + result1 = valuePayload1; + result2 = valuePayload2; + } else { + result = 0; + result1 = 0; + result2 = 0.0; + } + instance.exports.bjs_JSValueHolder_echoOptional(this.pointer, +isSome, result, result1, result2); const isSome1 = i32Stack.pop(); let optResult; if (isSome1) { @@ -435,8 +458,20 @@ export async function createInstantiator(options, swift) { } set optionalValue(value) { const isSome = value != null; - const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); - instance.exports.bjs_JSValueHolder_optionalValue_set(this.pointer, +isSome, valueKind, valuePayload1, valuePayload2); + let result; + let result1; + let result2; + if (isSome) { + const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); + result = valueKind; + result1 = valuePayload1; + result2 = valuePayload2; + } else { + result = 0; + result1 = 0; + result2 = 0.0; + } + instance.exports.bjs_JSValueHolder_optionalValue_set(this.pointer, +isSome, result, result1, result2); } } const exports = { @@ -452,8 +487,20 @@ export async function createInstantiator(options, swift) { }, roundTripOptionalJSValue: function bjs_roundTripOptionalJSValue(value) { const isSome = value != null; - const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); - instance.exports.bjs_roundTripOptionalJSValue(+isSome, valueKind, valuePayload1, valuePayload2); + let result; + let result1; + let result2; + if (isSome) { + const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); + result = valueKind; + result1 = valuePayload1; + result2 = valuePayload2; + } else { + result = 0; + result1 = 0; + result2 = 0.0; + } + instance.exports.bjs_roundTripOptionalJSValue(+isSome, result, result1, result2); const isSome1 = i32Stack.pop(); let optResult; if (isSome1) { @@ -468,7 +515,6 @@ export async function createInstantiator(options, swift) { return optResult; }, roundTripJSValueArray: function bjs_roundTripJSValueArray(values) { - const arrayCleanups = []; for (const elem of values) { const [elemKind, elemPayload1, elemPayload2] = __bjs_jsValueLower(elem); i32Stack.push(elemKind); @@ -487,14 +533,11 @@ export async function createInstantiator(options, swift) { arrayResult.push(jsValue); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, roundTripOptionalJSValueArray: function bjs_roundTripOptionalJSValueArray(values) { const isSome = values != null; - const valuesCleanups = []; if (isSome) { - const arrayCleanups = []; for (const elem of values) { const [elemKind, elemPayload1, elemPayload2] = __bjs_jsValueLower(elem); i32Stack.push(elemKind); @@ -502,7 +545,6 @@ export async function createInstantiator(options, swift) { f64Stack.push(elemPayload2); } i32Stack.push(values.length); - valuesCleanups.push(() => { for (const cleanup of arrayCleanups) { cleanup(); } }); } i32Stack.push(+isSome); instance.exports.bjs_roundTripOptionalJSValueArray(); @@ -523,7 +565,6 @@ export async function createInstantiator(options, swift) { } else { optResult = null; } - for (const cleanup of valuesCleanups) { cleanup(); } return optResult; }, }; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js index 675aa3798..2f6ed59f4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -76,8 +75,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -94,16 +92,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js index 6a6c75ef4..b35f72617 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -76,8 +75,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -94,16 +92,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js index f36211310..c1a0d7386 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -76,8 +75,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -94,16 +92,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js index 09ad002a1..984818d0c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -76,8 +75,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -94,16 +92,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js index 7368e52fa..d1fa886f9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -76,8 +75,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -94,16 +92,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js index c4f99c84b..9e15a2004 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -77,8 +76,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -95,16 +93,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -209,19 +197,25 @@ export async function createInstantiator(options, swift) { return swift.memory.retain(obj); }; const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_WithOptionalJSClass_init"] = function bjs_WithOptionalJSClass_init(valueOrNullIsSome, valueOrNullWrappedValue, valueOrUndefinedIsSome, valueOrUndefinedWrappedValue) { + TestModule["bjs_WithOptionalJSClass_init"] = function bjs_WithOptionalJSClass_init(valueOrNullIsSome, valueOrNullObjectId, valueOrUndefinedIsSome, valueOrUndefinedObjectId) { try { - let obj; + let optResult; if (valueOrNullIsSome) { - obj = swift.memory.getObject(valueOrNullWrappedValue); - swift.memory.release(valueOrNullWrappedValue); + const valueOrNullObjectIdObject = swift.memory.getObject(valueOrNullObjectId); + swift.memory.release(valueOrNullObjectId); + optResult = valueOrNullObjectIdObject; + } else { + optResult = null; } - let obj1; + let optResult1; if (valueOrUndefinedIsSome) { - obj1 = swift.memory.getObject(valueOrUndefinedWrappedValue); - swift.memory.release(valueOrUndefinedWrappedValue); + const valueOrUndefinedObjectIdObject = swift.memory.getObject(valueOrUndefinedObjectId); + swift.memory.release(valueOrUndefinedObjectId); + optResult1 = valueOrUndefinedObjectIdObject; + } else { + optResult1 = undefined; } - return swift.memory.retain(new imports.WithOptionalJSClass(valueOrNullIsSome ? obj : null, valueOrUndefinedIsSome ? obj1 : undefined)); + return swift.memory.retain(new imports.WithOptionalJSClass(optResult, optResult1)); } catch (error) { setException(error); return 0 @@ -231,11 +225,7 @@ export async function createInstantiator(options, swift) { try { let ret = swift.memory.getObject(self).stringOrNull; const isSome = ret != null; - if (isSome) { - tmpRetString = ret; - } else { - tmpRetString = null; - } + tmpRetString = isSome ? ret : null; } catch (error) { setException(error); } @@ -244,11 +234,7 @@ export async function createInstantiator(options, swift) { try { let ret = swift.memory.getObject(self).stringOrUndefined; const isSome = ret !== undefined; - if (isSome) { - tmpRetString = ret; - } else { - tmpRetString = null; - } + tmpRetString = isSome ? ret : undefined; } catch (error) { setException(error); } @@ -307,26 +293,32 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_WithOptionalJSClass_stringOrNull_set"] = function bjs_WithOptionalJSClass_stringOrNull_set(self, newValueIsSome, newValueWrappedValue) { + TestModule["bjs_WithOptionalJSClass_stringOrNull_set"] = function bjs_WithOptionalJSClass_stringOrNull_set(self, newValueIsSome, newValueObjectId) { try { - let obj; + let optResult; if (newValueIsSome) { - obj = swift.memory.getObject(newValueWrappedValue); - swift.memory.release(newValueWrappedValue); + const newValueObjectIdObject = swift.memory.getObject(newValueObjectId); + swift.memory.release(newValueObjectId); + optResult = newValueObjectIdObject; + } else { + optResult = null; } - swift.memory.getObject(self).stringOrNull = newValueIsSome ? obj : null; + swift.memory.getObject(self).stringOrNull = optResult; } catch (error) { setException(error); } } - TestModule["bjs_WithOptionalJSClass_stringOrUndefined_set"] = function bjs_WithOptionalJSClass_stringOrUndefined_set(self, newValueIsSome, newValueWrappedValue) { + TestModule["bjs_WithOptionalJSClass_stringOrUndefined_set"] = function bjs_WithOptionalJSClass_stringOrUndefined_set(self, newValueIsSome, newValueObjectId) { try { - let obj; + let optResult; if (newValueIsSome) { - obj = swift.memory.getObject(newValueWrappedValue); - swift.memory.release(newValueWrappedValue); + const newValueObjectIdObject = swift.memory.getObject(newValueObjectId); + swift.memory.release(newValueObjectId); + optResult = newValueObjectIdObject; + } else { + optResult = undefined; } - swift.memory.getObject(self).stringOrUndefined = newValueIsSome ? obj : undefined; + swift.memory.getObject(self).stringOrUndefined = optResult; } catch (error) { setException(error); } @@ -373,38 +365,36 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_WithOptionalJSClass_roundTripStringOrNull"] = function bjs_WithOptionalJSClass_roundTripStringOrNull(self, valueIsSome, valueWrappedValue) { + TestModule["bjs_WithOptionalJSClass_roundTripStringOrNull"] = function bjs_WithOptionalJSClass_roundTripStringOrNull(self, valueIsSome, valueObjectId) { try { - let obj; + let optResult; if (valueIsSome) { - obj = swift.memory.getObject(valueWrappedValue); - swift.memory.release(valueWrappedValue); - } - let ret = swift.memory.getObject(self).roundTripStringOrNull(valueIsSome ? obj : null); - const isSome = ret != null; - if (isSome) { - tmpRetString = ret; + const valueObjectIdObject = swift.memory.getObject(valueObjectId); + swift.memory.release(valueObjectId); + optResult = valueObjectIdObject; } else { - tmpRetString = null; + optResult = null; } + let ret = swift.memory.getObject(self).roundTripStringOrNull(optResult); + const isSome = ret != null; + tmpRetString = isSome ? ret : null; } catch (error) { setException(error); } } - TestModule["bjs_WithOptionalJSClass_roundTripStringOrUndefined"] = function bjs_WithOptionalJSClass_roundTripStringOrUndefined(self, valueIsSome, valueWrappedValue) { + TestModule["bjs_WithOptionalJSClass_roundTripStringOrUndefined"] = function bjs_WithOptionalJSClass_roundTripStringOrUndefined(self, valueIsSome, valueObjectId) { try { - let obj; + let optResult; if (valueIsSome) { - obj = swift.memory.getObject(valueWrappedValue); - swift.memory.release(valueWrappedValue); - } - let ret = swift.memory.getObject(self).roundTripStringOrUndefined(valueIsSome ? obj : undefined); - const isSome = ret !== undefined; - if (isSome) { - tmpRetString = ret; + const valueObjectIdObject = swift.memory.getObject(valueObjectId); + swift.memory.release(valueObjectId); + optResult = valueObjectIdObject; } else { - tmpRetString = null; + optResult = undefined; } + let ret = swift.memory.getObject(self).roundTripStringOrUndefined(optResult); + const isSome = ret !== undefined; + tmpRetString = isSome ? ret : undefined; } catch (error) { setException(error); } @@ -501,12 +491,18 @@ export async function createInstantiator(options, swift) { constructor(name) { const isSome = name != null; - let nameId, nameBytes; + let result; + let result1; if (isSome) { - nameBytes = textEncoder.encode(name); - nameId = swift.memory.retain(nameBytes); + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + result = nameId; + result1 = nameBytes.length; + } else { + result = 0; + result1 = 0; } - const ret = instance.exports.bjs_Greeter_init(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + const ret = instance.exports.bjs_Greeter_init(+isSome, result, result1); return Greeter.__construct(ret); } greet() { @@ -517,12 +513,18 @@ export async function createInstantiator(options, swift) { } changeName(name) { const isSome = name != null; - let nameId, nameBytes; + let result; + let result1; if (isSome) { - nameBytes = textEncoder.encode(name); - nameId = swift.memory.retain(nameBytes); + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + result = nameId; + result1 = nameBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_Greeter_changeName(this.pointer, +isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + instance.exports.bjs_Greeter_changeName(this.pointer, +isSome, result, result1); } get name() { instance.exports.bjs_Greeter_name_get(this.pointer); @@ -532,12 +534,18 @@ export async function createInstantiator(options, swift) { } set name(value) { const isSome = value != null; - let valueId, valueBytes; + let result; + let result1; if (isSome) { - valueBytes = textEncoder.encode(value); - valueId = swift.memory.retain(valueBytes); + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + result = valueId; + result1 = valueBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_Greeter_name_set(this.pointer, +isSome, isSome ? valueId : 0, isSome ? valueBytes.length : 0); + instance.exports.bjs_Greeter_name_set(this.pointer, +isSome, result, result1); } } class OptionalPropertyHolder extends SwiftHeapObject { @@ -557,12 +565,18 @@ export async function createInstantiator(options, swift) { } set optionalName(value) { const isSome = value != null; - let valueId, valueBytes; + let result; + let result1; if (isSome) { - valueBytes = textEncoder.encode(value); - valueId = swift.memory.retain(valueBytes); + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + result = valueId; + result1 = valueBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_OptionalPropertyHolder_optionalName_set(this.pointer, +isSome, isSome ? valueId : 0, isSome ? valueBytes.length : 0); + instance.exports.bjs_OptionalPropertyHolder_optionalName_set(this.pointer, +isSome, result, result1); } get optionalAge() { instance.exports.bjs_OptionalPropertyHolder_optionalAge_get(this.pointer); @@ -583,7 +597,13 @@ export async function createInstantiator(options, swift) { } set optionalGreeter(value) { const isSome = value != null; - instance.exports.bjs_OptionalPropertyHolder_optionalGreeter_set(this.pointer, +isSome, isSome ? value.pointer : 0); + let result; + if (isSome) { + result = value.pointer; + } else { + result = 0; + } + instance.exports.bjs_OptionalPropertyHolder_optionalGreeter_set(this.pointer, +isSome, result); } } const exports = { @@ -591,7 +611,13 @@ export async function createInstantiator(options, swift) { OptionalPropertyHolder, roundTripOptionalClass: function bjs_roundTripOptionalClass(value) { const isSome = value != null; - instance.exports.bjs_roundTripOptionalClass(+isSome, isSome ? value.pointer : 0); + let result; + if (isSome) { + result = value.pointer; + } else { + result = 0; + } + instance.exports.bjs_roundTripOptionalClass(+isSome, result); const pointer = tmpRetOptionalHeapObject; tmpRetOptionalHeapObject = undefined; const optResult = pointer === null ? null : Greeter.__construct(pointer); @@ -599,7 +625,13 @@ export async function createInstantiator(options, swift) { }, testOptionalPropertyRoundtrip: function bjs_testOptionalPropertyRoundtrip(holder) { const isSome = holder != null; - instance.exports.bjs_testOptionalPropertyRoundtrip(+isSome, isSome ? holder.pointer : 0); + let result; + if (isSome) { + result = holder.pointer; + } else { + result = 0; + } + instance.exports.bjs_testOptionalPropertyRoundtrip(+isSome, result); const pointer = tmpRetOptionalHeapObject; tmpRetOptionalHeapObject = undefined; const optResult = pointer === null ? null : OptionalPropertyHolder.__construct(pointer); @@ -607,12 +639,18 @@ export async function createInstantiator(options, swift) { }, roundTripString: function bjs_roundTripString(name) { const isSome = name != null; - let nameId, nameBytes; + let result; + let result1; if (isSome) { - nameBytes = textEncoder.encode(name); - nameId = swift.memory.retain(nameBytes); + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + result = nameId; + result1 = nameBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_roundTripString(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + instance.exports.bjs_roundTripString(+isSome, result, result1); const optResult = tmpRetString; tmpRetString = undefined; return optResult; @@ -626,76 +664,100 @@ export async function createInstantiator(options, swift) { }, roundTripBool: function bjs_roundTripBool(flag) { const isSome = flag != null; - instance.exports.bjs_roundTripBool(+isSome, isSome ? flag : 0); + instance.exports.bjs_roundTripBool(+isSome, isSome ? flag ? 1 : 0 : 0); const optResult = tmpRetOptionalBool; tmpRetOptionalBool = undefined; return optResult; }, roundTripFloat: function bjs_roundTripFloat(number) { const isSome = number != null; - instance.exports.bjs_roundTripFloat(+isSome, isSome ? number : 0); + instance.exports.bjs_roundTripFloat(+isSome, isSome ? number : 0.0); const optResult = tmpRetOptionalFloat; tmpRetOptionalFloat = undefined; return optResult; }, roundTripDouble: function bjs_roundTripDouble(precision) { const isSome = precision != null; - instance.exports.bjs_roundTripDouble(+isSome, isSome ? precision : 0); + instance.exports.bjs_roundTripDouble(+isSome, isSome ? precision : 0.0); const optResult = tmpRetOptionalDouble; tmpRetOptionalDouble = undefined; return optResult; }, roundTripSyntax: function bjs_roundTripSyntax(name) { const isSome = name != null; - let nameId, nameBytes; + let result; + let result1; if (isSome) { - nameBytes = textEncoder.encode(name); - nameId = swift.memory.retain(nameBytes); + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + result = nameId; + result1 = nameBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_roundTripSyntax(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + instance.exports.bjs_roundTripSyntax(+isSome, result, result1); const optResult = tmpRetString; tmpRetString = undefined; return optResult; }, roundTripMixSyntax: function bjs_roundTripMixSyntax(name) { const isSome = name != null; - let nameId, nameBytes; + let result; + let result1; if (isSome) { - nameBytes = textEncoder.encode(name); - nameId = swift.memory.retain(nameBytes); + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + result = nameId; + result1 = nameBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_roundTripMixSyntax(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + instance.exports.bjs_roundTripMixSyntax(+isSome, result, result1); const optResult = tmpRetString; tmpRetString = undefined; return optResult; }, roundTripSwiftSyntax: function bjs_roundTripSwiftSyntax(name) { const isSome = name != null; - let nameId, nameBytes; + let result; + let result1; if (isSome) { - nameBytes = textEncoder.encode(name); - nameId = swift.memory.retain(nameBytes); + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + result = nameId; + result1 = nameBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_roundTripSwiftSyntax(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + instance.exports.bjs_roundTripSwiftSyntax(+isSome, result, result1); const optResult = tmpRetString; tmpRetString = undefined; return optResult; }, roundTripMixedSwiftSyntax: function bjs_roundTripMixedSwiftSyntax(name) { const isSome = name != null; - let nameId, nameBytes; + let result; + let result1; if (isSome) { - nameBytes = textEncoder.encode(name); - nameId = swift.memory.retain(nameBytes); + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + result = nameId; + result1 = nameBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_roundTripMixedSwiftSyntax(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + instance.exports.bjs_roundTripMixedSwiftSyntax(+isSome, result, result1); const optResult = tmpRetString; tmpRetString = undefined; return optResult; }, roundTripWithSpaces: function bjs_roundTripWithSpaces(value) { const isSome = value != null; - instance.exports.bjs_roundTripWithSpaces(+isSome, isSome ? value : 0); + instance.exports.bjs_roundTripWithSpaces(+isSome, isSome ? value : 0.0); const optResult = tmpRetOptionalDouble; tmpRetOptionalDouble = undefined; return optResult; @@ -709,31 +771,49 @@ export async function createInstantiator(options, swift) { }, roundTripOptionalAlias: function bjs_roundTripOptionalAlias(name) { const isSome = name != null; - let nameId, nameBytes; + let result; + let result1; if (isSome) { - nameBytes = textEncoder.encode(name); - nameId = swift.memory.retain(nameBytes); + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + result = nameId; + result1 = nameBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_roundTripOptionalAlias(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + instance.exports.bjs_roundTripOptionalAlias(+isSome, result, result1); const optResult = tmpRetString; tmpRetString = undefined; return optResult; }, testMixedOptionals: function bjs_testMixedOptionals(firstName, lastName, age, active) { const isSome = firstName != null; - let firstNameId, firstNameBytes; + let result; + let result1; if (isSome) { - firstNameBytes = textEncoder.encode(firstName); - firstNameId = swift.memory.retain(firstNameBytes); + const firstNameBytes = textEncoder.encode(firstName); + const firstNameId = swift.memory.retain(firstNameBytes); + result = firstNameId; + result1 = firstNameBytes.length; + } else { + result = 0; + result1 = 0; } const isSome1 = lastName != null; - let lastNameId, lastNameBytes; + let result2; + let result3; if (isSome1) { - lastNameBytes = textEncoder.encode(lastName); - lastNameId = swift.memory.retain(lastNameBytes); + const lastNameBytes = textEncoder.encode(lastName); + const lastNameId = swift.memory.retain(lastNameBytes); + result2 = lastNameId; + result3 = lastNameBytes.length; + } else { + result2 = 0; + result3 = 0; } const isSome2 = age != null; - instance.exports.bjs_testMixedOptionals(+isSome, isSome ? firstNameId : 0, isSome ? firstNameBytes.length : 0, +isSome1, isSome1 ? lastNameId : 0, isSome1 ? lastNameBytes.length : 0, +isSome2, isSome2 ? age : 0, active); + instance.exports.bjs_testMixedOptionals(+isSome, result, result1, +isSome1, result2, result3, +isSome2, isSome2 ? age : 0, active); const optResult = tmpRetString; tmpRetString = undefined; return optResult; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js index 83c77397a..47e529b83 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -77,8 +76,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -95,16 +93,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js index f1fda2cb7..52194d346 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -77,8 +76,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -95,16 +93,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js index b39362233..72d45b279 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -76,8 +75,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -94,16 +92,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js index 1d413db20..9e8536c27 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js @@ -47,49 +47,44 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; let _exports = null; let bjs = null; - const __bjs_createResultValuesHelpers = () => { - return () => ({ - lower: (value) => { - const enumTag = value.tag; - switch (enumTag) { - case ResultValues.Tag.Success: { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - const cleanup = undefined; - return { caseId: ResultValues.Tag.Success, cleanup }; - } - case ResultValues.Tag.Failure: { - i32Stack.push((value.param0 | 0)); - const cleanup = undefined; - return { caseId: ResultValues.Tag.Failure, cleanup }; - } - default: throw new Error("Unknown ResultValues tag: " + String(enumTag)); - } - }, - lift: (tag) => { - tag = tag | 0; - switch (tag) { - case ResultValues.Tag.Success: { - const string = strStack.pop(); - return { tag: ResultValues.Tag.Success, param0: string }; - } - case ResultValues.Tag.Failure: { - const int = i32Stack.pop(); - return { tag: ResultValues.Tag.Failure, param0: int }; - } - default: throw new Error("Unknown ResultValues tag returned from Swift: " + String(tag)); + const __bjs_createResultValuesHelpers = () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case ResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + return ResultValues.Tag.Success; + } + case ResultValues.Tag.Failure: { + i32Stack.push((value.param0 | 0)); + return ResultValues.Tag.Failure; + } + default: throw new Error("Unknown ResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case ResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: ResultValues.Tag.Success, param0: string }; } + case ResultValues.Tag.Failure: { + const int = i32Stack.pop(); + return { tag: ResultValues.Tag.Failure, param0: int }; + } + default: throw new Error("Unknown ResultValues tag returned from Swift: " + String(tag)); } - }); - }; + } + }); return { /** @@ -137,8 +132,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -155,16 +149,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -306,14 +290,17 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_MyViewControllerDelegate_optionalName_set"] = function bjs_MyViewControllerDelegate_optionalName_set(self, valueIsSome, valueWrappedValue) { + TestModule["bjs_MyViewControllerDelegate_optionalName_set"] = function bjs_MyViewControllerDelegate_optionalName_set(self, valueIsSome, valueObjectId) { try { - let obj; + let optResult; if (valueIsSome) { - obj = swift.memory.getObject(valueWrappedValue); - swift.memory.release(valueWrappedValue); + const valueObjectIdObject = swift.memory.getObject(valueObjectId); + swift.memory.release(valueObjectId); + optResult = valueObjectIdObject; + } else { + optResult = null; } - swift.memory.getObject(self).optionalName = valueIsSome ? obj : null; + swift.memory.getObject(self).optionalName = optResult; } catch (error) { setException(error); } @@ -326,14 +313,17 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_MyViewControllerDelegate_optionalRawEnum_set"] = function bjs_MyViewControllerDelegate_optionalRawEnum_set(self, valueIsSome, valueWrappedValue) { + TestModule["bjs_MyViewControllerDelegate_optionalRawEnum_set"] = function bjs_MyViewControllerDelegate_optionalRawEnum_set(self, valueIsSome, valueObjectId) { try { - let obj; + let optResult; if (valueIsSome) { - obj = swift.memory.getObject(valueWrappedValue); - swift.memory.release(valueWrappedValue); + const valueObjectIdObject = swift.memory.getObject(valueObjectId); + swift.memory.release(valueObjectId); + optResult = valueObjectIdObject; + } else { + optResult = null; } - swift.memory.getObject(self).optionalRawEnum = valueIsSome ? obj : null; + swift.memory.getObject(self).optionalRawEnum = optResult; } catch (error) { setException(error); } @@ -359,7 +349,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_MyViewControllerDelegate_result_get"] = function bjs_MyViewControllerDelegate_result_get(self) { try { let ret = swift.memory.getObject(self).result; - const { caseId: caseId, cleanup: cleanup } = enumHelpers.Result.lower(ret); + const caseId = enumHelpers.Result.lower(ret); return caseId; } catch (error) { setException(error); @@ -378,7 +368,7 @@ export async function createInstantiator(options, swift) { let ret = swift.memory.getObject(self).optionalResult; const isSome = ret != null; if (isSome) { - const { caseId: caseId, cleanup: cleanup } = enumHelpers.Result.lower(ret); + const caseId = enumHelpers.Result.lower(ret); return caseId; } else { return -1; @@ -387,13 +377,16 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_MyViewControllerDelegate_optionalResult_set"] = function bjs_MyViewControllerDelegate_optionalResult_set(self, valueIsSome, valueWrappedValue) { + TestModule["bjs_MyViewControllerDelegate_optionalResult_set"] = function bjs_MyViewControllerDelegate_optionalResult_set(self, valueIsSome, valueCaseId) { try { - let enumValue; + let optResult; if (valueIsSome) { - enumValue = enumHelpers.Result.lift(valueWrappedValue); + const enumValue = enumHelpers.Result.lift(valueCaseId); + optResult = enumValue; + } else { + optResult = null; } - swift.memory.getObject(self).optionalResult = valueIsSome ? enumValue : null; + swift.memory.getObject(self).optionalResult = optResult; } catch (error) { setException(error); } @@ -418,7 +411,7 @@ export async function createInstantiator(options, swift) { try { let ret = swift.memory.getObject(self).directionOptional; const isSome = ret != null; - return isSome ? (ret | 0) : -1; + return isSome ? ret : -1; } catch (error) { setException(error); } @@ -522,9 +515,9 @@ export async function createInstantiator(options, swift) { return 0 } } - TestModule["bjs_MyViewControllerDelegate_onOptionalHelperUpdated"] = function bjs_MyViewControllerDelegate_onOptionalHelperUpdated(self, helperIsSome, helperWrappedValue) { + TestModule["bjs_MyViewControllerDelegate_onOptionalHelperUpdated"] = function bjs_MyViewControllerDelegate_onOptionalHelperUpdated(self, helperIsSome, helperPointer) { try { - swift.memory.getObject(self).onOptionalHelperUpdated(helperIsSome ? _exports['Helper'].__construct(helperWrappedValue) : null); + swift.memory.getObject(self).onOptionalHelperUpdated(helperIsSome ? _exports['Helper'].__construct(helperPointer) : null); } catch (error) { setException(error); } @@ -558,7 +551,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_MyViewControllerDelegate_getResult"] = function bjs_MyViewControllerDelegate_getResult(self) { try { let ret = swift.memory.getObject(self).getResult(); - const { caseId: caseId, cleanup: cleanup } = enumHelpers.Result.lower(ret); + const caseId = enumHelpers.Result.lower(ret); return caseId; } catch (error) { setException(error); @@ -667,7 +660,13 @@ export async function createInstantiator(options, swift) { } set secondDelegate(value) { const isSome = value != null; - instance.exports.bjs_MyViewController_secondDelegate_set(this.pointer, +isSome, isSome ? swift.memory.retain(value) : 0); + let result; + if (isSome) { + result = swift.memory.retain(value); + } else { + result = 0; + } + instance.exports.bjs_MyViewController_secondDelegate_set(this.pointer, +isSome, result); } } class DelegateManager extends SwiftHeapObject { @@ -676,14 +675,12 @@ export async function createInstantiator(options, swift) { } constructor(delegates) { - const arrayCleanups = []; for (const elem of delegates) { const objId = swift.memory.retain(elem); i32Stack.push(objId); } i32Stack.push(delegates.length); const ret = instance.exports.bjs_DelegateManager_init(); - for (const cleanup of arrayCleanups) { cleanup(); } return DelegateManager.__construct(ret); } notifyAll() { @@ -703,17 +700,15 @@ export async function createInstantiator(options, swift) { return arrayResult; } set delegates(value) { - const arrayCleanups = []; for (const elem of value) { const objId = swift.memory.retain(elem); i32Stack.push(objId); } i32Stack.push(value.length); instance.exports.bjs_DelegateManager_delegates_set(this.pointer); - for (const cleanup of arrayCleanups) { cleanup(); } } } - const ResultHelpers = __bjs_createResultValuesHelpers()(); + const ResultHelpers = __bjs_createResultValuesHelpers(); enumHelpers.Result = ResultHelpers; const exports = { @@ -721,7 +716,6 @@ export async function createInstantiator(options, swift) { MyViewController, DelegateManager, processDelegates: function bjs_processDelegates(delegates) { - const arrayCleanups = []; for (const elem of delegates) { const objId = swift.memory.retain(elem); i32Stack.push(objId); @@ -737,7 +731,6 @@ export async function createInstantiator(options, swift) { arrayResult.push(obj); } arrayResult.reverse(); - for (const cleanup of arrayCleanups) { cleanup(); } return arrayResult; }, Direction: DirectionValues, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js index 07f7a3c77..43883e34f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js @@ -34,49 +34,44 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; let _exports = null; let bjs = null; - const __bjs_createAPIResultValuesHelpers = () => { - return () => ({ - lower: (value) => { - const enumTag = value.tag; - switch (enumTag) { - case APIResultValues.Tag.Success: { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - const cleanup = undefined; - return { caseId: APIResultValues.Tag.Success, cleanup }; - } - case APIResultValues.Tag.Failure: { - i32Stack.push((value.param0 | 0)); - const cleanup = undefined; - return { caseId: APIResultValues.Tag.Failure, cleanup }; - } - default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); + const __bjs_createAPIResultValuesHelpers = () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case APIResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + return APIResultValues.Tag.Success; } - }, - lift: (tag) => { - tag = tag | 0; - switch (tag) { - case APIResultValues.Tag.Success: { - const string = strStack.pop(); - return { tag: APIResultValues.Tag.Success, param0: string }; - } - case APIResultValues.Tag.Failure: { - const int = i32Stack.pop(); - return { tag: APIResultValues.Tag.Failure, param0: int }; - } - default: throw new Error("Unknown APIResultValues tag returned from Swift: " + String(tag)); + case APIResultValues.Tag.Failure: { + i32Stack.push((value.param0 | 0)); + return APIResultValues.Tag.Failure; + } + default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case APIResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: APIResultValues.Tag.Success, param0: string }; + } + case APIResultValues.Tag.Failure: { + const int = i32Stack.pop(); + return { tag: APIResultValues.Tag.Failure, param0: int }; } + default: throw new Error("Unknown APIResultValues tag returned from Swift: " + String(tag)); } - }); - }; + } + }); return { /** @@ -124,8 +119,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -142,16 +136,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -304,7 +288,7 @@ export async function createInstantiator(options, swift) { return ret; } } - const APIResultHelpers = __bjs_createAPIResultValuesHelpers()(); + const APIResultHelpers = __bjs_createAPIResultValuesHelpers(); enumHelpers.APIResult = APIResultHelpers; if (typeof globalThis.Utils === 'undefined') { @@ -325,10 +309,9 @@ export async function createInstantiator(options, swift) { APIResult: { ...APIResultValues, roundtrip: function(value) { - const { caseId: valueCaseId, cleanup: valueCleanup } = enumHelpers.APIResult.lower(value); + const valueCaseId = enumHelpers.APIResult.lower(value); instance.exports.bjs_APIResult_static_roundtrip(valueCaseId); const ret = enumHelpers.APIResult.lift(i32Stack.pop()); - if (valueCleanup) { valueCleanup(); } return ret; } }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js index c2c3f9a70..1b48b9ad3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js @@ -34,49 +34,44 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; let _exports = null; let bjs = null; - const __bjs_createAPIResultValuesHelpers = () => { - return () => ({ - lower: (value) => { - const enumTag = value.tag; - switch (enumTag) { - case APIResultValues.Tag.Success: { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - const cleanup = undefined; - return { caseId: APIResultValues.Tag.Success, cleanup }; - } - case APIResultValues.Tag.Failure: { - i32Stack.push((value.param0 | 0)); - const cleanup = undefined; - return { caseId: APIResultValues.Tag.Failure, cleanup }; - } - default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); + const __bjs_createAPIResultValuesHelpers = () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case APIResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + return APIResultValues.Tag.Success; } - }, - lift: (tag) => { - tag = tag | 0; - switch (tag) { - case APIResultValues.Tag.Success: { - const string = strStack.pop(); - return { tag: APIResultValues.Tag.Success, param0: string }; - } - case APIResultValues.Tag.Failure: { - const int = i32Stack.pop(); - return { tag: APIResultValues.Tag.Failure, param0: int }; - } - default: throw new Error("Unknown APIResultValues tag returned from Swift: " + String(tag)); + case APIResultValues.Tag.Failure: { + i32Stack.push((value.param0 | 0)); + return APIResultValues.Tag.Failure; + } + default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case APIResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: APIResultValues.Tag.Success, param0: string }; + } + case APIResultValues.Tag.Failure: { + const int = i32Stack.pop(); + return { tag: APIResultValues.Tag.Failure, param0: int }; } + default: throw new Error("Unknown APIResultValues tag returned from Swift: " + String(tag)); } - }); - }; + } + }); return { /** @@ -124,8 +119,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -142,16 +136,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -304,7 +288,7 @@ export async function createInstantiator(options, swift) { return ret; } } - const APIResultHelpers = __bjs_createAPIResultValuesHelpers()(); + const APIResultHelpers = __bjs_createAPIResultValuesHelpers(); enumHelpers.APIResult = APIResultHelpers; const exports = { @@ -319,10 +303,9 @@ export async function createInstantiator(options, swift) { APIResult: { ...APIResultValues, roundtrip: function(value) { - const { caseId: valueCaseId, cleanup: valueCleanup } = enumHelpers.APIResult.lower(value); + const valueCaseId = enumHelpers.APIResult.lower(value); instance.exports.bjs_APIResult_static_roundtrip(valueCaseId); const ret = enumHelpers.APIResult.lift(i32Stack.pop()); - if (valueCleanup) { valueCleanup(); } return ret; } }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js index 3784b5a7e..427289cf2 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js @@ -28,7 +28,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -81,8 +80,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -99,16 +97,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -304,12 +292,18 @@ export async function createInstantiator(options, swift) { } static set optionalProperty(value) { const isSome = value != null; - let valueId, valueBytes; + let result; + let result1; if (isSome) { - valueBytes = textEncoder.encode(value); - valueId = swift.memory.retain(valueBytes); + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + result = valueId; + result1 = valueBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_PropertyClass_static_optionalProperty_set(+isSome, isSome ? valueId : 0, isSome ? valueBytes.length : 0); + instance.exports.bjs_PropertyClass_static_optionalProperty_set(+isSome, result, result1); } } if (typeof globalThis.PropertyNamespace === 'undefined') { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js index 47f0092af..c549eaa88 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js @@ -28,7 +28,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -81,8 +80,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -99,16 +97,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -304,12 +292,18 @@ export async function createInstantiator(options, swift) { } static set optionalProperty(value) { const isSome = value != null; - let valueId, valueBytes; + let result; + let result1; if (isSome) { - valueBytes = textEncoder.encode(value); - valueId = swift.memory.retain(valueBytes); + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + result = valueId; + result1 = valueBytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.bjs_PropertyClass_static_optionalProperty_set(+isSome, isSome ? valueId : 0, isSome ? valueBytes.length : 0); + instance.exports.bjs_PropertyClass_static_optionalProperty_set(+isSome, result, result1); } } const exports = { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js index 0f92074d4..5842e12ea 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -77,8 +76,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -95,16 +93,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js index f86fce218..ace7b1eac 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -77,8 +76,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -95,16 +93,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js index 9f8f93c5b..53135230c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -77,8 +76,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -95,16 +93,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -222,9 +210,9 @@ export async function createInstantiator(options, swift) { return 0 } } - TestModule["bjs_jsRoundTripOptionalGreeter"] = function bjs_jsRoundTripOptionalGreeter(greeterIsSome, greeterWrappedValue) { + TestModule["bjs_jsRoundTripOptionalGreeter"] = function bjs_jsRoundTripOptionalGreeter(greeterIsSome, greeterPointer) { try { - let ret = imports.jsRoundTripOptionalGreeter(greeterIsSome ? _exports['Greeter'].__construct(greeterWrappedValue) : null); + let ret = imports.jsRoundTripOptionalGreeter(greeterIsSome ? _exports['Greeter'].__construct(greeterPointer) : null); const isSome = ret != null; return isSome ? ret.pointer : 0; } catch (error) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js index 3371cf1b3..688a61ada 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js @@ -53,7 +53,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -84,75 +83,67 @@ export async function createInstantiator(options, swift) { return swift.memory.retain(real); }; - const __bjs_createAPIResultValuesHelpers = () => { - return () => ({ - lower: (value) => { - const enumTag = value.tag; - switch (enumTag) { - case APIResultValues.Tag.Success: { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - const cleanup = undefined; - return { caseId: APIResultValues.Tag.Success, cleanup }; - } - case APIResultValues.Tag.Failure: { - i32Stack.push((value.param0 | 0)); - const cleanup = undefined; - return { caseId: APIResultValues.Tag.Failure, cleanup }; - } - case APIResultValues.Tag.Flag: { - i32Stack.push(value.param0 ? 1 : 0); - const cleanup = undefined; - return { caseId: APIResultValues.Tag.Flag, cleanup }; - } - case APIResultValues.Tag.Rate: { - f32Stack.push(Math.fround(value.param0)); - const cleanup = undefined; - return { caseId: APIResultValues.Tag.Rate, cleanup }; - } - case APIResultValues.Tag.Precise: { - f64Stack.push(value.param0); - const cleanup = undefined; - return { caseId: APIResultValues.Tag.Precise, cleanup }; - } - case APIResultValues.Tag.Info: { - const cleanup = undefined; - return { caseId: APIResultValues.Tag.Info, cleanup }; - } - default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); + const __bjs_createAPIResultValuesHelpers = () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case APIResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + return APIResultValues.Tag.Success; } - }, - lift: (tag) => { - tag = tag | 0; - switch (tag) { - case APIResultValues.Tag.Success: { - const string = strStack.pop(); - return { tag: APIResultValues.Tag.Success, param0: string }; - } - case APIResultValues.Tag.Failure: { - const int = i32Stack.pop(); - return { tag: APIResultValues.Tag.Failure, param0: int }; - } - case APIResultValues.Tag.Flag: { - const bool = i32Stack.pop() !== 0; - return { tag: APIResultValues.Tag.Flag, param0: bool }; - } - case APIResultValues.Tag.Rate: { - const f32 = f32Stack.pop(); - return { tag: APIResultValues.Tag.Rate, param0: f32 }; - } - case APIResultValues.Tag.Precise: { - const f64 = f64Stack.pop(); - return { tag: APIResultValues.Tag.Precise, param0: f64 }; - } - case APIResultValues.Tag.Info: return { tag: APIResultValues.Tag.Info }; - default: throw new Error("Unknown APIResultValues tag returned from Swift: " + String(tag)); + case APIResultValues.Tag.Failure: { + i32Stack.push((value.param0 | 0)); + return APIResultValues.Tag.Failure; + } + case APIResultValues.Tag.Flag: { + i32Stack.push(value.param0 ? 1 : 0); + return APIResultValues.Tag.Flag; + } + case APIResultValues.Tag.Rate: { + f32Stack.push(Math.fround(value.param0)); + return APIResultValues.Tag.Rate; } + case APIResultValues.Tag.Precise: { + f64Stack.push(value.param0); + return APIResultValues.Tag.Precise; + } + case APIResultValues.Tag.Info: { + return APIResultValues.Tag.Info; + } + default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); } - }); - }; + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case APIResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: APIResultValues.Tag.Success, param0: string }; + } + case APIResultValues.Tag.Failure: { + const int = i32Stack.pop(); + return { tag: APIResultValues.Tag.Failure, param0: int }; + } + case APIResultValues.Tag.Flag: { + const bool = i32Stack.pop() !== 0; + return { tag: APIResultValues.Tag.Flag, param0: bool }; + } + case APIResultValues.Tag.Rate: { + const f32 = f32Stack.pop(); + return { tag: APIResultValues.Tag.Rate, param0: f32 }; + } + case APIResultValues.Tag.Precise: { + const f64 = f64Stack.pop(); + return { tag: APIResultValues.Tag.Precise, param0: f64 }; + } + case APIResultValues.Tag.Info: return { tag: APIResultValues.Tag.Info }; + default: throw new Error("Unknown APIResultValues tag returned from Swift: " + String(tag)); + } + } + }); return { /** @@ -200,8 +191,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -218,16 +208,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -403,7 +383,7 @@ export async function createInstantiator(options, swift) { const callback = swift.memory.getObject(callbackId); const enumValue = enumHelpers.APIResult.lift(param0); let ret = callback(enumValue); - const { caseId: caseId, cleanup: cleanup } = enumHelpers.APIResult.lower(ret); + const caseId = enumHelpers.APIResult.lower(ret); return caseId; } catch (error) { setException(error); @@ -411,10 +391,9 @@ export async function createInstantiator(options, swift) { } bjs["make_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModule9APIResultO_9APIResultO = function(param0) { - const { caseId: param0CaseId, cleanup: param0Cleanup } = enumHelpers.APIResult.lower(param0); + const param0CaseId = enumHelpers.APIResult.lower(param0); instance.exports.invoke_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO(boxPtr, param0CaseId); const ret = enumHelpers.APIResult.lift(i32Stack.pop()); - if (param0Cleanup) { param0Cleanup(); } if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); @@ -595,21 +574,20 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO); } - bjs["invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO"] = function(callbackId, param0IsSome, param0WrappedValue) { + bjs["invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO"] = function(callbackId, param0IsSome, param0ObjectId) { try { const callback = swift.memory.getObject(callbackId); - let obj; + let optResult; if (param0IsSome) { - obj = swift.memory.getObject(param0WrappedValue); - swift.memory.release(param0WrappedValue); - } - let ret = callback(param0IsSome ? obj : null); - const isSome = ret != null; - if (isSome) { - tmpRetString = ret; + const param0ObjectIdObject = swift.memory.getObject(param0ObjectId); + swift.memory.release(param0ObjectId); + optResult = param0ObjectIdObject; } else { - tmpRetString = null; + optResult = null; } + let ret = callback(optResult); + const isSome = ret != null; + tmpRetString = isSome ? ret : null; } catch (error) { setException(error); } @@ -617,12 +595,18 @@ export async function createInstantiator(options, swift) { bjs["make_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO = function(param0) { const isSome = param0 != null; - let param0Id, param0Bytes; + let result; + let result1; if (isSome) { - param0Bytes = textEncoder.encode(param0); - param0Id = swift.memory.retain(param0Bytes); + const param0Bytes = textEncoder.encode(param0); + const param0Id = swift.memory.retain(param0Bytes); + result = param0Id; + result1 = param0Bytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(boxPtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(boxPtr, +isSome, result, result1); const optResult = tmpRetString; tmpRetString = undefined; if (tmpRetException) { @@ -635,10 +619,10 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO); } - bjs["invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC"] = function(callbackId, param0IsSome, param0WrappedValue) { + bjs["invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC"] = function(callbackId, param0IsSome, param0Pointer) { try { const callback = swift.memory.getObject(callbackId); - let ret = callback(param0IsSome ? _exports['Person'].__construct(param0WrappedValue) : null); + let ret = callback(param0IsSome ? _exports['Person'].__construct(param0Pointer) : null); const isSome = ret != null; return isSome ? ret.pointer : 0; } catch (error) { @@ -648,7 +632,13 @@ export async function createInstantiator(options, swift) { bjs["make_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC = function(param0) { const isSome = param0 != null; - instance.exports.invoke_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC(boxPtr, +isSome, isSome ? param0.pointer : 0); + let result; + if (isSome) { + result = param0.pointer; + } else { + result = 0; + } + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC(boxPtr, +isSome, result); const pointer = tmpRetOptionalHeapObject; tmpRetOptionalHeapObject = undefined; const optResult = pointer === null ? null : _exports['Person'].__construct(pointer); @@ -662,17 +652,20 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC); } - bjs["invoke_js_callback_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO"] = function(callbackId, param0IsSome, param0WrappedValue) { + bjs["invoke_js_callback_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO"] = function(callbackId, param0IsSome, param0CaseId) { try { const callback = swift.memory.getObject(callbackId); - let enumValue; + let optResult; if (param0IsSome) { - enumValue = enumHelpers.APIResult.lift(param0WrappedValue); + const enumValue = enumHelpers.APIResult.lift(param0CaseId); + optResult = enumValue; + } else { + optResult = null; } - let ret = callback(param0IsSome ? enumValue : null); + let ret = callback(optResult); const isSome = ret != null; if (isSome) { - const { caseId: caseId, cleanup: cleanup } = enumHelpers.APIResult.lower(ret); + const caseId = enumHelpers.APIResult.lower(ret); return caseId; } else { return -1; @@ -684,22 +677,16 @@ export async function createInstantiator(options, swift) { bjs["make_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO = function(param0) { const isSome = param0 != null; - let param0CaseId, param0Cleanup; + let result; if (isSome) { - const enumResult = enumHelpers.APIResult.lower(param0); - param0CaseId = enumResult.caseId; - param0Cleanup = enumResult.cleanup; - } - instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(boxPtr, +isSome, isSome ? param0CaseId : 0); - const tag = i32Stack.pop(); - const isNull = (tag === -1); - let optResult; - if (isNull) { - optResult = null; + const param0CaseId = enumHelpers.APIResult.lower(param0); + result = param0CaseId; } else { - optResult = enumHelpers.APIResult.lift(tag); + result = 0; } - if (param0Cleanup) { param0Cleanup(); } + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(boxPtr, +isSome, result); + const tag = i32Stack.pop(); + const optResult = tag === -1 ? null : enumHelpers.APIResult.lift(tag); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); @@ -715,7 +702,7 @@ export async function createInstantiator(options, swift) { const callback = swift.memory.getObject(callbackId); let ret = callback(param0IsSome ? param0WrappedValue : null); const isSome = ret != null; - return isSome ? (ret | 0) : -1; + return isSome ? ret : -1; } catch (error) { setException(error); } @@ -736,21 +723,20 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO); } - bjs["invoke_js_callback_TestModule_10TestModuleSqSS_SqSS"] = function(callbackId, param0IsSome, param0WrappedValue) { + bjs["invoke_js_callback_TestModule_10TestModuleSqSS_SqSS"] = function(callbackId, param0IsSome, param0ObjectId) { try { const callback = swift.memory.getObject(callbackId); - let obj; + let optResult; if (param0IsSome) { - obj = swift.memory.getObject(param0WrappedValue); - swift.memory.release(param0WrappedValue); - } - let ret = callback(param0IsSome ? obj : null); - const isSome = ret != null; - if (isSome) { - tmpRetString = ret; + const param0ObjectIdObject = swift.memory.getObject(param0ObjectId); + swift.memory.release(param0ObjectId); + optResult = param0ObjectIdObject; } else { - tmpRetString = null; + optResult = null; } + let ret = callback(optResult); + const isSome = ret != null; + tmpRetString = isSome ? ret : null; } catch (error) { setException(error); } @@ -758,12 +744,18 @@ export async function createInstantiator(options, swift) { bjs["make_swift_closure_TestModule_10TestModuleSqSS_SqSS"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSqSS_SqSS = function(param0) { const isSome = param0 != null; - let param0Id, param0Bytes; + let result; + let result1; if (isSome) { - param0Bytes = textEncoder.encode(param0); - param0Id = swift.memory.retain(param0Bytes); + const param0Bytes = textEncoder.encode(param0); + const param0Id = swift.memory.retain(param0Bytes); + result = param0Id; + result1 = param0Bytes.length; + } else { + result = 0; + result1 = 0; } - instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSS_SqSS(boxPtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSS_SqSS(boxPtr, +isSome, result, result1); const optResult = tmpRetString; tmpRetString = undefined; if (tmpRetException) { @@ -789,7 +781,7 @@ export async function createInstantiator(options, swift) { bjs["make_swift_closure_TestModule_10TestModuleSqSb_SqSb"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSqSb_SqSb = function(param0) { const isSome = param0 != null; - instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSb_SqSb(boxPtr, +isSome, isSome ? param0 : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSb_SqSb(boxPtr, +isSome, isSome ? param0 ? 1 : 0 : 0); const optResult = tmpRetOptionalBool; tmpRetOptionalBool = undefined; if (tmpRetException) { @@ -815,7 +807,7 @@ export async function createInstantiator(options, swift) { bjs["make_swift_closure_TestModule_10TestModuleSqSd_SqSd"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSqSd_SqSd = function(param0) { const isSome = param0 != null; - instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSd_SqSd(boxPtr, +isSome, isSome ? param0 : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSd_SqSd(boxPtr, +isSome, isSome ? param0 : 0.0); const optResult = tmpRetOptionalDouble; tmpRetOptionalDouble = undefined; if (tmpRetException) { @@ -841,7 +833,7 @@ export async function createInstantiator(options, swift) { bjs["make_swift_closure_TestModule_10TestModuleSqSf_SqSf"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSqSf_SqSf = function(param0) { const isSome = param0 != null; - instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSf_SqSf(boxPtr, +isSome, isSome ? param0 : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSf_SqSf(boxPtr, +isSome, isSome ? param0 : 0.0); const optResult = tmpRetOptionalFloat; tmpRetOptionalFloat = undefined; if (tmpRetException) { @@ -946,7 +938,7 @@ export async function createInstantiator(options, swift) { return TestProcessor.__construct(ret); } } - const APIResultHelpers = __bjs_createAPIResultValuesHelpers()(); + const APIResultHelpers = __bjs_createAPIResultValuesHelpers(); enumHelpers.APIResult = APIResultHelpers; const exports = { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js index 61347e817..5c6a41a08 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -102,8 +101,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -120,16 +118,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js index 316dfb709..41631e580 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js @@ -28,242 +28,219 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; let _exports = null; let bjs = null; - const __bjs_createDataPointHelpers = () => { - return () => ({ - lower: (value) => { - f64Stack.push(value.x); - f64Stack.push(value.y); - const bytes = textEncoder.encode(value.label); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - const isSome = value.optCount != null; - if (isSome) { - i32Stack.push(value.optCount | 0); - } else { - i32Stack.push(0); - } - i32Stack.push(isSome ? 1 : 0); - const isSome1 = value.optFlag != null; - if (isSome1) { - i32Stack.push(value.optFlag ? 1 : 0); - } else { - i32Stack.push(0); - } - i32Stack.push(isSome1 ? 1 : 0); - return { cleanup: undefined }; - }, - lift: () => { - const isSome = i32Stack.pop(); - let optional; - if (isSome) { - const bool = i32Stack.pop() !== 0; - optional = bool; - } else { - optional = null; - } - const isSome1 = i32Stack.pop(); - let optional1; - if (isSome1) { - const int = i32Stack.pop(); - optional1 = int; - } else { - optional1 = null; - } - const string = strStack.pop(); - const f64 = f64Stack.pop(); - const f641 = f64Stack.pop(); - return { x: f641, y: f64, label: string, optCount: optional1, optFlag: optional }; - } - }); - }; - const __bjs_createAddressHelpers = () => { - return () => ({ - lower: (value) => { - const bytes = textEncoder.encode(value.street); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - const bytes1 = textEncoder.encode(value.city); + const __bjs_createDataPointHelpers = () => ({ + lower: (value) => { + f64Stack.push(value.x); + f64Stack.push(value.y); + const bytes = textEncoder.encode(value.label); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const isSome = value.optCount != null; + if (isSome) { + i32Stack.push((value.optCount | 0)); + } else { + i32Stack.push(0); + } + i32Stack.push(isSome ? 1 : 0); + const isSome1 = value.optFlag != null; + if (isSome1) { + i32Stack.push(value.optFlag ? 1 : 0); + } else { + i32Stack.push(0); + } + i32Stack.push(isSome1 ? 1 : 0); + }, + lift: () => { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const bool = i32Stack.pop() !== 0; + optional = bool; + } else { + optional = null; + } + const isSome1 = i32Stack.pop(); + let optional1; + if (isSome1) { + const int = i32Stack.pop(); + optional1 = int; + } else { + optional1 = null; + } + const string = strStack.pop(); + const f64 = f64Stack.pop(); + const f641 = f64Stack.pop(); + return { x: f641, y: f64, label: string, optCount: optional1, optFlag: optional }; + } + }); + const __bjs_createAddressHelpers = () => ({ + lower: (value) => { + const bytes = textEncoder.encode(value.street); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const bytes1 = textEncoder.encode(value.city); + const id1 = swift.memory.retain(bytes1); + i32Stack.push(bytes1.length); + i32Stack.push(id1); + const isSome = value.zipCode != null; + if (isSome) { + i32Stack.push((value.zipCode | 0)); + } else { + i32Stack.push(0); + } + i32Stack.push(isSome ? 1 : 0); + }, + lift: () => { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const int = i32Stack.pop(); + optional = int; + } else { + optional = null; + } + const string = strStack.pop(); + const string1 = strStack.pop(); + return { street: string1, city: string, zipCode: optional }; + } + }); + const __bjs_createPersonHelpers = () => ({ + lower: (value) => { + const bytes = textEncoder.encode(value.name); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + i32Stack.push((value.age | 0)); + structHelpers.Address.lower(value.address); + const isSome = value.email != null; + if (isSome) { + const bytes1 = textEncoder.encode(value.email); const id1 = swift.memory.retain(bytes1); i32Stack.push(bytes1.length); i32Stack.push(id1); - const isSome = value.zipCode != null; - if (isSome) { - i32Stack.push(value.zipCode | 0); - } else { - i32Stack.push(0); - } - i32Stack.push(isSome ? 1 : 0); - return { cleanup: undefined }; - }, - lift: () => { - const isSome = i32Stack.pop(); - let optional; - if (isSome) { - const int = i32Stack.pop(); - optional = int; - } else { - optional = null; - } + } else { + i32Stack.push(0); + i32Stack.push(0); + } + i32Stack.push(isSome ? 1 : 0); + }, + lift: () => { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { const string = strStack.pop(); - const string1 = strStack.pop(); - return { street: string1, city: string, zipCode: optional }; - } - }); - }; - const __bjs_createPersonHelpers = () => { - return () => ({ - lower: (value) => { - const bytes = textEncoder.encode(value.name); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); - i32Stack.push(id); - i32Stack.push((value.age | 0)); - const structResult = structHelpers.Address.lower(value.address); - const isSome = value.email != null; - let id1; - if (isSome) { - const bytes1 = textEncoder.encode(value.email); - id1 = swift.memory.retain(bytes1); - i32Stack.push(bytes1.length); - i32Stack.push(id1); - } else { - i32Stack.push(0); - i32Stack.push(0); - } - i32Stack.push(isSome ? 1 : 0); - const cleanup = () => { - if (structResult.cleanup) { structResult.cleanup(); } - }; - return { cleanup }; - }, - lift: () => { - const isSome = i32Stack.pop(); - let optional; - if (isSome) { - const string = strStack.pop(); - optional = string; - } else { - optional = null; - } - const struct = structHelpers.Address.lift(); - const int = i32Stack.pop(); - const string1 = strStack.pop(); - return { name: string1, age: int, address: struct, email: optional }; - } - }); - }; - const __bjs_createSessionHelpers = () => { - return () => ({ - lower: (value) => { - i32Stack.push((value.id | 0)); - ptrStack.push(value.owner.pointer); - return { cleanup: undefined }; - }, - lift: () => { - const ptr = ptrStack.pop(); - const obj = _exports['Greeter'].__construct(ptr); - const int = i32Stack.pop(); - return { id: int, owner: obj }; - } - }); - }; - const __bjs_createMeasurementHelpers = () => { - return () => ({ - lower: (value) => { - f64Stack.push(value.value); - f32Stack.push(Math.fround(value.precision)); - const isSome = value.optionalPrecision != null; - if (isSome) { - f32Stack.push(Math.fround(value.optionalPrecision)); - } else { - f32Stack.push(0.0); - } - i32Stack.push(isSome ? 1 : 0); - return { cleanup: undefined }; - }, - lift: () => { - const isSome = i32Stack.pop(); - let optional; - if (isSome) { - const rawValue = f32Stack.pop(); - optional = rawValue; - } else { - optional = null; - } - const rawValue1 = f32Stack.pop(); - const f64 = f64Stack.pop(); - return { value: f64, precision: rawValue1, optionalPrecision: optional }; - } - }); - }; - const __bjs_createConfigStructHelpers = () => { - return () => ({ - lower: (value) => { - return { cleanup: undefined }; - }, - lift: () => { - return { }; - } - }); - }; - const __bjs_createContainerHelpers = () => { - return () => ({ - lower: (value) => { - let id; - if (value.object != null) { - id = swift.memory.retain(value.object); - } else { - id = undefined; - } - i32Stack.push(id !== undefined ? id : 0); - const isSome = value.optionalObject != null; + optional = string; + } else { + optional = null; + } + const struct = structHelpers.Address.lift(); + const int = i32Stack.pop(); + const string1 = strStack.pop(); + return { name: string1, age: int, address: struct, email: optional }; + } + }); + const __bjs_createSessionHelpers = () => ({ + lower: (value) => { + i32Stack.push((value.id | 0)); + ptrStack.push(value.owner.pointer); + }, + lift: () => { + const ptr = ptrStack.pop(); + const obj = _exports['Greeter'].__construct(ptr); + const int = i32Stack.pop(); + return { id: int, owner: obj }; + } + }); + const __bjs_createMeasurementHelpers = () => ({ + lower: (value) => { + f64Stack.push(value.value); + f32Stack.push(Math.fround(value.precision)); + const isSome = value.optionalPrecision != null; + if (isSome) { + f32Stack.push(Math.fround(value.optionalPrecision)); + } else { + f32Stack.push(0.0); + } + i32Stack.push(isSome ? 1 : 0); + }, + lift: () => { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const rawValue = f32Stack.pop(); + optional = rawValue; + } else { + optional = null; + } + const rawValue1 = f32Stack.pop(); + const f64 = f64Stack.pop(); + return { value: f64, precision: rawValue1, optionalPrecision: optional }; + } + }); + const __bjs_createConfigStructHelpers = () => ({ + lower: (value) => { + }, + lift: () => { + return { }; + } + }); + const __bjs_createContainerHelpers = () => ({ + lower: (value) => { + let id; + if (value.object != null) { + id = swift.memory.retain(value.object); + } else { + id = undefined; + } + i32Stack.push(id !== undefined ? id : 0); + const isSome = value.optionalObject != null; + if (isSome) { let id1; - if (isSome) { + if (value.optionalObject != null) { id1 = swift.memory.retain(value.optionalObject); - i32Stack.push(id1); } else { id1 = undefined; - i32Stack.push(0); } - i32Stack.push(isSome ? 1 : 0); - return { cleanup: undefined }; - }, - lift: () => { - const isSome = i32Stack.pop(); - let optional; - if (isSome) { - const objectId = i32Stack.pop(); - let value; - if (objectId !== 0) { - value = swift.memory.getObject(objectId); - swift.memory.release(objectId); - } else { - value = null; - } - optional = value; - } else { - optional = null; - } - const objectId1 = i32Stack.pop(); - let value1; - if (objectId1 !== 0) { - value1 = swift.memory.getObject(objectId1); - swift.memory.release(objectId1); - } else { - value1 = null; - } - return { object: value1, optionalObject: optional }; + i32Stack.push(id1 !== undefined ? id1 : 0); + } else { + i32Stack.push(0); } - }); - }; + i32Stack.push(isSome ? 1 : 0); + }, + lift: () => { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const objectId = i32Stack.pop(); + let value; + if (objectId !== 0) { + value = swift.memory.getObject(objectId); + swift.memory.release(objectId); + } else { + value = null; + } + optional = value; + } else { + optional = null; + } + const objectId1 = i32Stack.pop(); + let value1; + if (objectId1 !== 0) { + value1 = swift.memory.getObject(objectId1); + swift.memory.release(objectId1); + } else { + value1 = null; + } + return { object: value1, optionalObject: optional }; + } + }); return { /** @@ -311,8 +288,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -329,88 +305,50 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_struct_lower_DataPoint"] = function(objectId) { - const { cleanup: cleanup } = structHelpers.DataPoint.lower(swift.memory.getObject(objectId)); - if (cleanup) { - return tmpStructCleanups.push(cleanup); - } - return 0; + structHelpers.DataPoint.lower(swift.memory.getObject(objectId)); } bjs["swift_js_struct_lift_DataPoint"] = function() { const value = structHelpers.DataPoint.lift(); return swift.memory.retain(value); } bjs["swift_js_struct_lower_Address"] = function(objectId) { - const { cleanup: cleanup } = structHelpers.Address.lower(swift.memory.getObject(objectId)); - if (cleanup) { - return tmpStructCleanups.push(cleanup); - } - return 0; + structHelpers.Address.lower(swift.memory.getObject(objectId)); } bjs["swift_js_struct_lift_Address"] = function() { const value = structHelpers.Address.lift(); return swift.memory.retain(value); } bjs["swift_js_struct_lower_Person"] = function(objectId) { - const { cleanup: cleanup } = structHelpers.Person.lower(swift.memory.getObject(objectId)); - if (cleanup) { - return tmpStructCleanups.push(cleanup); - } - return 0; + structHelpers.Person.lower(swift.memory.getObject(objectId)); } bjs["swift_js_struct_lift_Person"] = function() { const value = structHelpers.Person.lift(); return swift.memory.retain(value); } bjs["swift_js_struct_lower_Session"] = function(objectId) { - const { cleanup: cleanup } = structHelpers.Session.lower(swift.memory.getObject(objectId)); - if (cleanup) { - return tmpStructCleanups.push(cleanup); - } - return 0; + structHelpers.Session.lower(swift.memory.getObject(objectId)); } bjs["swift_js_struct_lift_Session"] = function() { const value = structHelpers.Session.lift(); return swift.memory.retain(value); } bjs["swift_js_struct_lower_Measurement"] = function(objectId) { - const { cleanup: cleanup } = structHelpers.Measurement.lower(swift.memory.getObject(objectId)); - if (cleanup) { - return tmpStructCleanups.push(cleanup); - } - return 0; + structHelpers.Measurement.lower(swift.memory.getObject(objectId)); } bjs["swift_js_struct_lift_Measurement"] = function() { const value = structHelpers.Measurement.lift(); return swift.memory.retain(value); } bjs["swift_js_struct_lower_ConfigStruct"] = function(objectId) { - const { cleanup: cleanup } = structHelpers.ConfigStruct.lower(swift.memory.getObject(objectId)); - if (cleanup) { - return tmpStructCleanups.push(cleanup); - } - return 0; + structHelpers.ConfigStruct.lower(swift.memory.getObject(objectId)); } bjs["swift_js_struct_lift_ConfigStruct"] = function() { const value = structHelpers.ConfigStruct.lift(); return swift.memory.retain(value); } bjs["swift_js_struct_lower_Container"] = function(objectId) { - const { cleanup: cleanup } = structHelpers.Container.lower(swift.memory.getObject(objectId)); - if (cleanup) { - return tmpStructCleanups.push(cleanup); - } - return 0; + structHelpers.Container.lower(swift.memory.getObject(objectId)); } bjs["swift_js_struct_lift_Container"] = function() { const value = structHelpers.Container.lift(); @@ -575,41 +513,39 @@ export async function createInstantiator(options, swift) { instance.exports.bjs_Greeter_name_set(this.pointer, valueId, valueBytes.length); } } - const DataPointHelpers = __bjs_createDataPointHelpers()(); + const DataPointHelpers = __bjs_createDataPointHelpers(); structHelpers.DataPoint = DataPointHelpers; - const AddressHelpers = __bjs_createAddressHelpers()(); + const AddressHelpers = __bjs_createAddressHelpers(); structHelpers.Address = AddressHelpers; - const PersonHelpers = __bjs_createPersonHelpers()(); + const PersonHelpers = __bjs_createPersonHelpers(); structHelpers.Person = PersonHelpers; - const SessionHelpers = __bjs_createSessionHelpers()(); + const SessionHelpers = __bjs_createSessionHelpers(); structHelpers.Session = SessionHelpers; - const MeasurementHelpers = __bjs_createMeasurementHelpers()(); + const MeasurementHelpers = __bjs_createMeasurementHelpers(); structHelpers.Measurement = MeasurementHelpers; - const ConfigStructHelpers = __bjs_createConfigStructHelpers()(); + const ConfigStructHelpers = __bjs_createConfigStructHelpers(); structHelpers.ConfigStruct = ConfigStructHelpers; - const ContainerHelpers = __bjs_createContainerHelpers()(); + const ContainerHelpers = __bjs_createContainerHelpers(); structHelpers.Container = ContainerHelpers; const exports = { Greeter, roundtrip: function bjs_roundtrip(session) { - const { cleanup: cleanup } = structHelpers.Person.lower(session); + structHelpers.Person.lower(session); instance.exports.bjs_roundtrip(); const structValue = structHelpers.Person.lift(); - if (cleanup) { cleanup(); } return structValue; }, roundtripContainer: function bjs_roundtripContainer(container) { - const { cleanup: cleanup } = structHelpers.Container.lower(container); + structHelpers.Container.lower(container); instance.exports.bjs_roundtripContainer(); const structValue = structHelpers.Container.lift(); - if (cleanup) { cleanup(); } return structValue; }, Precision: PrecisionValues, @@ -619,7 +555,7 @@ export async function createInstantiator(options, swift) { const labelId = swift.memory.retain(labelBytes); const isSome = optCount != null; const isSome1 = optFlag != null; - instance.exports.bjs_DataPoint_init(x, y, labelId, labelBytes.length, +isSome, isSome ? optCount : 0, +isSome1, isSome1 ? optFlag : 0); + instance.exports.bjs_DataPoint_init(x, y, labelId, labelBytes.length, +isSome, isSome ? optCount : 0, +isSome1, isSome1 ? optFlag ? 1 : 0 : 0); const structValue = structHelpers.DataPoint.lift(); return structValue; }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js index 4962e659b..94c452a6e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js @@ -23,26 +23,22 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; let _exports = null; let bjs = null; - const __bjs_createPointHelpers = () => { - return () => ({ - lower: (value) => { - i32Stack.push((value.x | 0)); - i32Stack.push((value.y | 0)); - return { cleanup: undefined }; - }, - lift: () => { - const int = i32Stack.pop(); - const int1 = i32Stack.pop(); - return { x: int1, y: int }; - } - }); - }; + const __bjs_createPointHelpers = () => ({ + lower: (value) => { + i32Stack.push((value.x | 0)); + i32Stack.push((value.y | 0)); + }, + lift: () => { + const int = i32Stack.pop(); + const int1 = i32Stack.pop(); + return { x: int1, y: int }; + } + }); return { /** @@ -91,8 +87,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -109,22 +104,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_struct_lower_Point"] = function(objectId) { - const { cleanup: cleanup } = structHelpers.Point.lower(swift.memory.getObject(objectId)); - if (cleanup) { - return tmpStructCleanups.push(cleanup); - } - return 0; + structHelpers.Point.lower(swift.memory.getObject(objectId)); } bjs["swift_js_struct_lift_Point"] = function() { const value = structHelpers.Point.lift(); @@ -244,7 +225,7 @@ export async function createInstantiator(options, swift) { /** @param {WebAssembly.Instance} instance */ createExports: (instance) => { const js = swift.memory.heap; - const PointHelpers = __bjs_createPointHelpers()(); + const PointHelpers = __bjs_createPointHelpers(); structHelpers.Point = PointHelpers; const exports = { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js index 3726a48ae..ba4b5299b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -76,8 +75,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -94,16 +92,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js index 7c3627d13..1b3b9770d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js @@ -23,32 +23,28 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; let _exports = null; let bjs = null; - const __bjs_createPointerFieldsHelpers = () => { - return () => ({ - lower: (value) => { - ptrStack.push((value.raw | 0)); - ptrStack.push((value.mutRaw | 0)); - ptrStack.push((value.opaque | 0)); - ptrStack.push((value.ptr | 0)); - ptrStack.push((value.mutPtr | 0)); - return { cleanup: undefined }; - }, - lift: () => { - const pointer = ptrStack.pop(); - const pointer1 = ptrStack.pop(); - const pointer2 = ptrStack.pop(); - const pointer3 = ptrStack.pop(); - const pointer4 = ptrStack.pop(); - return { raw: pointer4, mutRaw: pointer3, opaque: pointer2, ptr: pointer1, mutPtr: pointer }; - } - }); - }; + const __bjs_createPointerFieldsHelpers = () => ({ + lower: (value) => { + ptrStack.push((value.raw | 0)); + ptrStack.push((value.mutRaw | 0)); + ptrStack.push((value.opaque | 0)); + ptrStack.push((value.ptr | 0)); + ptrStack.push((value.mutPtr | 0)); + }, + lift: () => { + const pointer = ptrStack.pop(); + const pointer1 = ptrStack.pop(); + const pointer2 = ptrStack.pop(); + const pointer3 = ptrStack.pop(); + const pointer4 = ptrStack.pop(); + return { raw: pointer4, mutRaw: pointer3, opaque: pointer2, ptr: pointer1, mutPtr: pointer }; + } + }); return { /** @@ -96,8 +92,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -114,22 +109,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_struct_lower_PointerFields"] = function(objectId) { - const { cleanup: cleanup } = structHelpers.PointerFields.lower(swift.memory.getObject(objectId)); - if (cleanup) { - return tmpStructCleanups.push(cleanup); - } - return 0; + structHelpers.PointerFields.lower(swift.memory.getObject(objectId)); } bjs["swift_js_struct_lift_PointerFields"] = function() { const value = structHelpers.PointerFields.lift(); @@ -238,7 +219,7 @@ export async function createInstantiator(options, swift) { /** @param {WebAssembly.Instance} instance */ createExports: (instance) => { const js = swift.memory.heap; - const PointerFieldsHelpers = __bjs_createPointerFieldsHelpers()(); + const PointerFieldsHelpers = __bjs_createPointerFieldsHelpers(); structHelpers.PointerFields = PointerFieldsHelpers; const exports = { @@ -278,10 +259,9 @@ export async function createInstantiator(options, swift) { return ret; }, roundTripPointerFields: function bjs_roundTripPointerFields(value) { - const { cleanup: cleanup } = structHelpers.PointerFields.lower(value); + structHelpers.PointerFields.lower(value); instance.exports.bjs_roundTripPointerFields(); const structValue = structHelpers.PointerFields.lift(); - if (cleanup) { cleanup(); } return structValue; }, PointerFields: { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js index e338c840d..58d7e813f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; - let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -77,8 +76,7 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_push_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); - const value = textDecoder.decode(bytes); - strStack.push(value); + strStack.push(textDecoder.decode(bytes)); } bjs["swift_js_pop_i32"] = function() { return i32Stack.pop(); @@ -95,16 +93,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_pointer"] = function() { return ptrStack.pop(); } - bjs["swift_js_struct_cleanup"] = function(cleanupId) { - if (cleanupId === 0) { return; } - const index = (cleanupId | 0) - 1; - const cleanup = tmpStructCleanups[index]; - tmpStructCleanups[index] = null; - if (cleanup) { cleanup(); } - while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { - tmpStructCleanups.pop(); - } - } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift index 28bdaa6db..15b5be9ee 100644 --- a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift +++ b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift @@ -818,21 +818,6 @@ private func _swift_js_pop_f64_extern() -> Float64 { _swift_js_pop_f64_extern() } -// MARK: Struct bridging helpers (JS-side lowering/raising) - -#if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_struct_cleanup") -private func _swift_js_struct_cleanup_extern(_ cleanupId: Int32) -#else -private func _swift_js_struct_cleanup_extern(_ cleanupId: Int32) { - _onlyAvailableOnWasm() -} -#endif - -@_spi(BridgeJS) @inline(never) public func _swift_js_struct_cleanup(_ cleanupId: Int32) { - _swift_js_struct_cleanup_extern(cleanupId) -} - // MARK: Wasm externs used by type lowering/lifting #if arch(wasm32) diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index 78c9014d7..a7d5f405e 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -1026,10 +1026,10 @@ extension JSTypedClosure where Signature == (Optional) -> String { @_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 { +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Pointer: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure - let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Pointer)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -1083,10 +1083,10 @@ extension JSTypedClosure where Signature == (Optional) -> Optional Void { +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Pointer: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure - let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Pointer)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -2720,10 +2720,7 @@ extension Point: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -2736,9 +2733,9 @@ extension Point: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Point") -fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -2771,10 +2768,7 @@ extension PointerFields: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_PointerFields(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_PointerFields(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -2787,9 +2781,9 @@ extension PointerFields: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_PointerFields") -fileprivate func _bjs_struct_lower_PointerFields(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_PointerFields(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_PointerFields(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_PointerFields(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -2841,10 +2835,7 @@ extension DataPoint: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_DataPoint(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_DataPoint(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -2857,9 +2848,9 @@ extension DataPoint: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_DataPoint") -fileprivate func _bjs_struct_lower_DataPoint(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_DataPoint(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_DataPoint(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_DataPoint(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -2897,10 +2888,7 @@ extension PublicPoint: _BridgedSwiftStruct { } public init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_PublicPoint(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_PublicPoint(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -2913,9 +2901,9 @@ extension PublicPoint: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_PublicPoint") -fileprivate func _bjs_struct_lower_PublicPoint(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_PublicPoint(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_PublicPoint(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_PublicPoint(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -2959,10 +2947,7 @@ extension Address: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_Address(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_Address(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -2975,9 +2960,9 @@ extension Address: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Address") -fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -3014,10 +2999,7 @@ extension Contact: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_Contact(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_Contact(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -3030,9 +3012,9 @@ extension Contact: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Contact") -fileprivate func _bjs_struct_lower_Contact(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_Contact(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_Contact(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_Contact(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -3071,10 +3053,7 @@ extension Config: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_Config(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_Config(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -3087,9 +3066,9 @@ extension Config: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Config") -fileprivate func _bjs_struct_lower_Config(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_Config(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_Config(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_Config(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -3120,10 +3099,7 @@ extension SessionData: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_SessionData(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_SessionData(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -3136,9 +3112,9 @@ extension SessionData: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_SessionData") -fileprivate func _bjs_struct_lower_SessionData(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_SessionData(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_SessionData(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_SessionData(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -3177,10 +3153,7 @@ extension ValidationReport: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_ValidationReport(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_ValidationReport(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -3193,9 +3166,9 @@ extension ValidationReport: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_ValidationReport") -fileprivate func _bjs_struct_lower_ValidationReport(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_ValidationReport(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_ValidationReport(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_ValidationReport(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -3246,10 +3219,7 @@ extension AdvancedConfig: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_AdvancedConfig(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_AdvancedConfig(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -3262,9 +3232,9 @@ extension AdvancedConfig: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_AdvancedConfig") -fileprivate func _bjs_struct_lower_AdvancedConfig(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_AdvancedConfig(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_AdvancedConfig(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_AdvancedConfig(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -3303,10 +3273,7 @@ extension MeasurementConfig: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_MeasurementConfig(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_MeasurementConfig(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -3319,9 +3286,9 @@ extension MeasurementConfig: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_MeasurementConfig") -fileprivate func _bjs_struct_lower_MeasurementConfig(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_MeasurementConfig(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_MeasurementConfig(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_MeasurementConfig(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -3346,10 +3313,7 @@ extension MathOperations: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_MathOperations(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_MathOperations(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -3362,9 +3326,9 @@ extension MathOperations: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_MathOperations") -fileprivate func _bjs_struct_lower_MathOperations(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_MathOperations(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_MathOperations(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_MathOperations(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -3439,10 +3403,7 @@ extension CopyableCart: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_CopyableCart(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_CopyableCart(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -3455,9 +3416,9 @@ extension CopyableCart: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_CopyableCart") -fileprivate func _bjs_struct_lower_CopyableCart(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_CopyableCart(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_CopyableCart(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_CopyableCart(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -3495,10 +3456,7 @@ extension CopyableCartItem: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_CopyableCartItem(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_CopyableCartItem(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -3511,9 +3469,9 @@ extension CopyableCartItem: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_CopyableCartItem") -fileprivate func _bjs_struct_lower_CopyableCartItem(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_CopyableCartItem(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_CopyableCartItem(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_CopyableCartItem(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -3542,10 +3500,7 @@ extension CopyableNestedCart: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_CopyableNestedCart(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_CopyableNestedCart(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -3558,9 +3513,9 @@ extension CopyableNestedCart: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_CopyableNestedCart") -fileprivate func _bjs_struct_lower_CopyableNestedCart(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_CopyableNestedCart(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_CopyableNestedCart(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_CopyableNestedCart(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -3598,10 +3553,7 @@ extension ConfigStruct: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_ConfigStruct(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_ConfigStruct(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -3614,9 +3566,9 @@ extension ConfigStruct: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_ConfigStruct") -fileprivate func _bjs_struct_lower_ConfigStruct(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_ConfigStruct(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_ConfigStruct(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_ConfigStruct(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -3711,10 +3663,7 @@ extension JSObjectContainer: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_JSObjectContainer(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_JSObjectContainer(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -3727,9 +3676,9 @@ extension JSObjectContainer: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_JSObjectContainer") -fileprivate func _bjs_struct_lower_JSObjectContainer(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_JSObjectContainer(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_JSObjectContainer(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_JSObjectContainer(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -3760,10 +3709,7 @@ extension FooContainer: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_FooContainer(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_FooContainer(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -3776,9 +3722,9 @@ extension FooContainer: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_FooContainer") -fileprivate func _bjs_struct_lower_FooContainer(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_FooContainer(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_FooContainer(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_FooContainer(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -3805,10 +3751,7 @@ extension ArrayMembers: _BridgedSwiftStruct { } init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = _bjs_struct_lower_ArrayMembers(jsObject.bridgeJSLowerParameter()) - defer { - _swift_js_struct_cleanup(__bjs_cleanupId) - } + _bjs_struct_lower_ArrayMembers(jsObject.bridgeJSLowerParameter()) self = Self.bridgeJSStackPop() } @@ -3821,9 +3764,9 @@ extension ArrayMembers: _BridgedSwiftStruct { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_struct_lower_ArrayMembers") -fileprivate func _bjs_struct_lower_ArrayMembers(_ objectId: Int32) -> Int32 +fileprivate func _bjs_struct_lower_ArrayMembers(_ objectId: Int32) -> Void #else -fileprivate func _bjs_struct_lower_ArrayMembers(_ objectId: Int32) -> Int32 { +fileprivate func _bjs_struct_lower_ArrayMembers(_ objectId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif @@ -5912,9 +5855,9 @@ public func _bjs_roundTripOptionalPayloadResultOpt(_ resultIsSome: Int32, _ resu @_expose(wasm, "bjs_roundTripOptionalClass") @_cdecl("bjs_roundTripOptionalClass") -public func _bjs_roundTripOptionalClass(_ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { +public func _bjs_roundTripOptionalClass(_ valueIsSome: Int32, _ valuePointer: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let ret = roundTripOptionalClass(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + let ret = roundTripOptionalClass(value: Optional.bridgeJSLiftParameter(valueIsSome, valuePointer)) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -5923,9 +5866,9 @@ public func _bjs_roundTripOptionalClass(_ valueIsSome: Int32, _ valueValue: Unsa @_expose(wasm, "bjs_roundTripOptionalGreeter") @_cdecl("bjs_roundTripOptionalGreeter") -public func _bjs_roundTripOptionalGreeter(_ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { +public func _bjs_roundTripOptionalGreeter(_ valueIsSome: Int32, _ valuePointer: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let ret = roundTripOptionalGreeter(_: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + let ret = roundTripOptionalGreeter(_: Optional.bridgeJSLiftParameter(valueIsSome, valuePointer)) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -5934,9 +5877,9 @@ public func _bjs_roundTripOptionalGreeter(_ valueIsSome: Int32, _ valueValue: Un @_expose(wasm, "bjs_applyOptionalGreeter") @_cdecl("bjs_applyOptionalGreeter") -public func _bjs_applyOptionalGreeter(_ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer, _ transform: Int32) -> Void { +public func _bjs_applyOptionalGreeter(_ valueIsSome: Int32, _ valuePointer: UnsafeMutableRawPointer, _ transform: Int32) -> Void { #if arch(wasm32) - let ret = applyOptionalGreeter(_: Optional.bridgeJSLiftParameter(valueIsSome, valueValue), _: _BJS_Closure_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC.bridgeJSLift(transform)) + let ret = applyOptionalGreeter(_: Optional.bridgeJSLiftParameter(valueIsSome, valuePointer), _: _BJS_Closure_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC.bridgeJSLift(transform)) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -5945,9 +5888,9 @@ public func _bjs_applyOptionalGreeter(_ valueIsSome: Int32, _ valueValue: Unsafe @_expose(wasm, "bjs_makeOptionalHolder") @_cdecl("bjs_makeOptionalHolder") -public func _bjs_makeOptionalHolder(_ nullableGreeterIsSome: Int32, _ nullableGreeterValue: UnsafeMutableRawPointer, _ undefinedNumberIsSome: Int32, _ undefinedNumberValue: Float64) -> UnsafeMutableRawPointer { +public func _bjs_makeOptionalHolder(_ nullableGreeterIsSome: Int32, _ nullableGreeterPointer: UnsafeMutableRawPointer, _ undefinedNumberIsSome: Int32, _ undefinedNumberValue: Float64) -> UnsafeMutableRawPointer { #if arch(wasm32) - let ret = makeOptionalHolder(nullableGreeter: Optional.bridgeJSLiftParameter(nullableGreeterIsSome, nullableGreeterValue), undefinedNumber: JSUndefinedOr.bridgeJSLiftParameter(undefinedNumberIsSome, undefinedNumberValue)) + let ret = makeOptionalHolder(nullableGreeter: Optional.bridgeJSLiftParameter(nullableGreeterIsSome, nullableGreeterPointer), undefinedNumber: JSUndefinedOr.bridgeJSLiftParameter(undefinedNumberIsSome, undefinedNumberValue)) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -7717,7 +7660,7 @@ public func _bjs_DataProcessorManager_setProcessorAPIResult(_ _self: UnsafeMutab @_cdecl("bjs_DataProcessorManager_processor_get") public func _bjs_DataProcessorManager_processor_get(_ _self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = DataProcessorManager.bridgeJSLiftParameter(_self).processor as! AnyDataProcessor + let ret = (DataProcessorManager.bridgeJSLiftParameter(_self).processor as! AnyDataProcessor) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -7868,9 +7811,9 @@ public func _bjs_SwiftDataProcessor_createGreeter(_ _self: UnsafeMutableRawPoint @_expose(wasm, "bjs_SwiftDataProcessor_processOptionalGreeter") @_cdecl("bjs_SwiftDataProcessor_processOptionalGreeter") -public func _bjs_SwiftDataProcessor_processOptionalGreeter(_ _self: UnsafeMutableRawPointer, _ greeterIsSome: Int32, _ greeterValue: UnsafeMutableRawPointer) -> Void { +public func _bjs_SwiftDataProcessor_processOptionalGreeter(_ _self: UnsafeMutableRawPointer, _ greeterIsSome: Int32, _ greeterPointer: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).processOptionalGreeter(_: Optional.bridgeJSLiftParameter(greeterIsSome, greeterValue)) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).processOptionalGreeter(_: Optional.bridgeJSLiftParameter(greeterIsSome, greeterPointer)) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -8101,9 +8044,9 @@ public func _bjs_SwiftDataProcessor_optionalHelper_get(_ _self: UnsafeMutableRaw @_expose(wasm, "bjs_SwiftDataProcessor_optionalHelper_set") @_cdecl("bjs_SwiftDataProcessor_optionalHelper_set") -public func _bjs_SwiftDataProcessor_optionalHelper_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { +public func _bjs_SwiftDataProcessor_optionalHelper_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valuePointer: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - SwiftDataProcessor.bridgeJSLiftParameter(_self).optionalHelper = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + SwiftDataProcessor.bridgeJSLiftParameter(_self).optionalHelper = Optional.bridgeJSLiftParameter(valueIsSome, valuePointer) #else fatalError("Only available on WebAssembly") #endif @@ -8392,9 +8335,9 @@ fileprivate func _bjs_TextProcessor_wrap(_ pointer: UnsafeMutableRawPointer) -> @_expose(wasm, "bjs_OptionalHolder_init") @_cdecl("bjs_OptionalHolder_init") -public func _bjs_OptionalHolder_init(_ nullableGreeterIsSome: Int32, _ nullableGreeterValue: UnsafeMutableRawPointer, _ undefinedNumberIsSome: Int32, _ undefinedNumberValue: Float64) -> UnsafeMutableRawPointer { +public func _bjs_OptionalHolder_init(_ nullableGreeterIsSome: Int32, _ nullableGreeterPointer: UnsafeMutableRawPointer, _ undefinedNumberIsSome: Int32, _ undefinedNumberValue: Float64) -> UnsafeMutableRawPointer { #if arch(wasm32) - let ret = OptionalHolder(nullableGreeter: Optional.bridgeJSLiftParameter(nullableGreeterIsSome, nullableGreeterValue), undefinedNumber: JSUndefinedOr.bridgeJSLiftParameter(undefinedNumberIsSome, undefinedNumberValue)) + let ret = OptionalHolder(nullableGreeter: Optional.bridgeJSLiftParameter(nullableGreeterIsSome, nullableGreeterPointer), undefinedNumber: JSUndefinedOr.bridgeJSLiftParameter(undefinedNumberIsSome, undefinedNumberValue)) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -8414,9 +8357,9 @@ public func _bjs_OptionalHolder_nullableGreeter_get(_ _self: UnsafeMutableRawPoi @_expose(wasm, "bjs_OptionalHolder_nullableGreeter_set") @_cdecl("bjs_OptionalHolder_nullableGreeter_set") -public func _bjs_OptionalHolder_nullableGreeter_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { +public func _bjs_OptionalHolder_nullableGreeter_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valuePointer: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - OptionalHolder.bridgeJSLiftParameter(_self).nullableGreeter = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + OptionalHolder.bridgeJSLiftParameter(_self).nullableGreeter = Optional.bridgeJSLiftParameter(valueIsSome, valuePointer) #else fatalError("Only available on WebAssembly") #endif @@ -8534,9 +8477,9 @@ public func _bjs_OptionalPropertyHolder_optionalGreeter_get(_ _self: UnsafeMutab @_expose(wasm, "bjs_OptionalPropertyHolder_optionalGreeter_set") @_cdecl("bjs_OptionalPropertyHolder_optionalGreeter_set") -public func _bjs_OptionalPropertyHolder_optionalGreeter_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { +public func _bjs_OptionalPropertyHolder_optionalGreeter_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valuePointer: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalGreeter = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalGreeter = Optional.bridgeJSLiftParameter(valueIsSome, valuePointer) #else fatalError("Only available on WebAssembly") #endif diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs index 58215560c..6a02eb180 100644 --- a/Tests/BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs +++ b/Tests/BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs @@ -1,6 +1,6 @@ // @ts-check -import assert from 'node:assert'; +import assert from "node:assert"; import { StatusValues, ThemeValues, @@ -11,9 +11,9 @@ import { APIOptionalResultValues, AllTypesResultValues, OptionalAllTypesResultValues, -} from '../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.js'; +} from "../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.js"; -import { ImportedFoo } from './Types.mjs'; +import { ImportedFoo } from "./Types.mjs"; /** * @returns {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Imports["OptionalSupportImports"]} @@ -34,7 +34,9 @@ export function getImports(importsContext) { }, runJsOptionalSupportTests: () => { const exports = importsContext.getExports(); - if (!exports) { throw new Error("No exports!?"); } + if (!exports) { + throw new Error("No exports!?"); + } runJsOptionalSupportTests(exports); }, }; @@ -51,50 +53,87 @@ export function runJsOptionalSupportTests(exports) { assert.equal(exports.roundTripOptionalFloat(null), null); assert.equal(exports.roundTripOptionalDouble(null), null); - assert.equal(exports.roundTripOptionalString('Hello'), 'Hello'); + assert.equal(exports.roundTripOptionalString("Hello"), "Hello"); assert.equal(exports.roundTripOptionalInt(42), 42); assert.equal(exports.roundTripOptionalBool(true), true); - assert.equal(exports.roundTripOptionalFloat(3.141592502593994), 3.141592502593994); // Float32 precision + assert.equal( + exports.roundTripOptionalFloat(3.141592502593994), + 3.141592502593994, + ); // Float32 precision assert.equal(exports.roundTripOptionalDouble(2.718), 2.718); assert.equal(exports.roundTripOptionalSyntax(null), null); - assert.equal(exports.roundTripOptionalSyntax('Test'), 'Test'); + assert.equal(exports.roundTripOptionalSyntax("Test"), "Test"); assert.equal(exports.roundTripOptionalMixSyntax(null), null); - assert.equal(exports.roundTripOptionalMixSyntax('Mix'), 'Mix'); + assert.equal(exports.roundTripOptionalMixSyntax("Mix"), "Mix"); assert.equal(exports.roundTripOptionalSwiftSyntax(null), null); - assert.equal(exports.roundTripOptionalSwiftSyntax('Swift'), 'Swift'); + assert.equal(exports.roundTripOptionalSwiftSyntax("Swift"), "Swift"); assert.equal(exports.roundTripOptionalWithSpaces(null), null); assert.equal(exports.roundTripOptionalWithSpaces(1.618), 1.618); assert.equal(exports.roundTripOptionalTypeAlias(null), null); assert.equal(exports.roundTripOptionalTypeAlias(25), 25); - assert.equal(exports.roundTripOptionalStatus(exports.Status.Success), StatusValues.Success); - assert.equal(exports.roundTripOptionalTheme(exports.Theme.Light), ThemeValues.Light); - assert.equal(exports.roundTripOptionalHttpStatus(exports.HttpStatus.Ok), HttpStatusValues.Ok); - assert.equal(exports.roundTripOptionalTSDirection(TSDirection.North), TSDirection.North); - assert.equal(exports.roundTripOptionalTSTheme(TSTheme.Light), TSTheme.Light); - assert.equal(exports.roundTripOptionalNetworkingAPIMethod(exports.Networking.API.Method.Get), exports.Networking.API.Method.Get); + assert.equal( + exports.roundTripOptionalStatus(exports.Status.Success), + StatusValues.Success, + ); + assert.equal( + exports.roundTripOptionalTheme(exports.Theme.Light), + ThemeValues.Light, + ); + assert.equal( + exports.roundTripOptionalHttpStatus(exports.HttpStatus.Ok), + HttpStatusValues.Ok, + ); + assert.equal( + exports.roundTripOptionalTSDirection(TSDirection.North), + TSDirection.North, + ); + assert.equal( + exports.roundTripOptionalTSTheme(TSTheme.Light), + TSTheme.Light, + ); + assert.equal( + exports.roundTripOptionalNetworkingAPIMethod( + exports.Networking.API.Method.Get, + ), + exports.Networking.API.Method.Get, + ); const pVal = 3.141592653589793; const p1 = { tag: APIResultValues.Tag.Precise, param0: pVal }; - const cl1 = { tag: exports.ComplexResult.Tag.Location, param0: 37.7749, param1: -122.4194, param2: 'San Francisco' }; + const cl1 = { + tag: exports.ComplexResult.Tag.Location, + param0: 37.7749, + param1: -122.4194, + param2: "San Francisco", + }; assert.deepEqual(exports.roundTripOptionalAPIResult(p1), p1); assert.deepEqual(exports.roundTripOptionalComplexResult(cl1), cl1); - const apiSuccess = { tag: exports.APIResult.Tag.Success, param0: 'test success' }; + const apiSuccess = { + tag: exports.APIResult.Tag.Success, + param0: "test success", + }; const apiFailure = { tag: exports.APIResult.Tag.Failure, param0: 404 }; const apiInfo = { tag: exports.APIResult.Tag.Info }; - assert.equal(exports.compareAPIResults(apiSuccess, apiFailure), 'r1:success:test success,r2:failure:404'); - assert.equal(exports.compareAPIResults(null, apiInfo), 'r1:nil,r2:info'); - assert.equal(exports.compareAPIResults(apiFailure, null), 'r1:failure:404,r2:nil'); - assert.equal(exports.compareAPIResults(null, null), 'r1:nil,r2:nil'); - - const optionalGreeter = new exports.Greeter('Schrödinger'); + assert.equal( + exports.compareAPIResults(apiSuccess, apiFailure), + "r1:success:test success,r2:failure:404", + ); + assert.equal(exports.compareAPIResults(null, apiInfo), "r1:nil,r2:info"); + assert.equal( + exports.compareAPIResults(apiFailure, null), + "r1:failure:404,r2:nil", + ); + assert.equal(exports.compareAPIResults(null, null), "r1:nil,r2:nil"); + + const optionalGreeter = new exports.Greeter("Schrödinger"); const optionalGreeter2 = exports.roundTripOptionalClass(optionalGreeter); - assert.equal(optionalGreeter2?.greet() ?? '', 'Hello, Schrödinger!'); - assert.equal(optionalGreeter2?.name ?? '', 'Schrödinger'); - assert.equal(optionalGreeter2?.prefix ?? '', 'Hello'); + assert.equal(optionalGreeter2?.greet() ?? "", "Hello, Schrödinger!"); + assert.equal(optionalGreeter2?.name ?? "", "Schrödinger"); + assert.equal(optionalGreeter2?.prefix ?? "", "Hello"); assert.equal(exports.roundTripOptionalClass(null), null); optionalGreeter.release(); optionalGreeter2?.release(); @@ -105,15 +144,15 @@ export function runJsOptionalSupportTests(exports) { assert.equal(optionalsHolder.optionalAge, null); assert.equal(optionalsHolder.optionalGreeter, null); - optionalsHolder.optionalName = 'Alice'; + optionalsHolder.optionalName = "Alice"; optionalsHolder.optionalAge = 25; - assert.equal(optionalsHolder.optionalName, 'Alice'); + assert.equal(optionalsHolder.optionalName, "Alice"); assert.equal(optionalsHolder.optionalAge, 25); - const testPropertyGreeter = new exports.Greeter('Bob'); + const testPropertyGreeter = new exports.Greeter("Bob"); optionalsHolder.optionalGreeter = testPropertyGreeter; - assert.equal(optionalsHolder.optionalGreeter.greet(), 'Hello, Bob!'); - assert.equal(optionalsHolder.optionalGreeter.name, 'Bob'); + assert.equal(optionalsHolder.optionalGreeter.greet(), "Hello, Bob!"); + assert.equal(optionalsHolder.optionalGreeter.name, "Bob"); optionalsHolder.optionalName = null; optionalsHolder.optionalAge = null; @@ -124,36 +163,79 @@ export function runJsOptionalSupportTests(exports) { testPropertyGreeter.release(); optionalsHolder.release(); - const optGreeter = new exports.Greeter('Optionaly'); + const optGreeter = new exports.Greeter("Optionaly"); assert.equal(exports.roundTripOptionalGreeter(null), null); const optGreeterReturned = exports.roundTripOptionalGreeter(optGreeter); - assert.equal(optGreeterReturned.name, 'Optionaly'); - assert.equal(optGreeterReturned.greet(), 'Hello, Optionaly!'); + assert.equal(optGreeterReturned.name, "Optionaly"); + assert.equal(optGreeterReturned.greet(), "Hello, Optionaly!"); - const appliedOptional = exports.applyOptionalGreeter(null, (g) => g ?? optGreeter); - assert.equal(appliedOptional.name, 'Optionaly'); + const appliedOptional = exports.applyOptionalGreeter( + null, + (g) => g ?? optGreeter, + ); + assert.equal(appliedOptional.name, "Optionaly"); const holderOpt = exports.makeOptionalHolder(null, undefined); assert.equal(holderOpt.nullableGreeter, null); assert.equal(holderOpt.undefinedNumber, undefined); holderOpt.nullableGreeter = optGreeter; holderOpt.undefinedNumber = 123.5; - assert.equal(holderOpt.nullableGreeter.name, 'Optionaly'); + assert.equal(holderOpt.nullableGreeter.name, "Optionaly"); assert.equal(holderOpt.undefinedNumber, 123.5); holderOpt.release(); optGreeterReturned.release(); optGreeter.release(); - const aor1 = { tag: APIOptionalResultValues.Tag.Success, param0: 'hello world' }; + const aor1 = { + tag: APIOptionalResultValues.Tag.Success, + param0: "hello world", + }; const aor2 = { tag: APIOptionalResultValues.Tag.Success, param0: null }; - const aor3 = { tag: APIOptionalResultValues.Tag.Failure, param0: 404, param1: true }; - const aor4 = { tag: APIOptionalResultValues.Tag.Failure, param0: 404, param1: null }; - const aor5 = { tag: APIOptionalResultValues.Tag.Failure, param0: null, param1: null }; - const aor6 = { tag: APIOptionalResultValues.Tag.Status, param0: true, param1: 200, param2: 'OK' }; - const aor7 = { tag: APIOptionalResultValues.Tag.Status, param0: true, param1: null, param2: 'Partial' }; - const aor8 = { tag: APIOptionalResultValues.Tag.Status, param0: null, param1: null, param2: 'Zero' }; - const aor9 = { tag: APIOptionalResultValues.Tag.Status, param0: false, param1: 500, param2: null }; - const aor10 = { tag: APIOptionalResultValues.Tag.Status, param0: null, param1: 0, param2: 'Zero' }; + const aor3 = { + tag: APIOptionalResultValues.Tag.Failure, + param0: 404, + param1: true, + }; + const aor4 = { + tag: APIOptionalResultValues.Tag.Failure, + param0: 404, + param1: null, + }; + const aor5 = { + tag: APIOptionalResultValues.Tag.Failure, + param0: null, + param1: null, + }; + const aor6 = { + tag: APIOptionalResultValues.Tag.Status, + param0: true, + param1: 200, + param2: "OK", + }; + const aor7 = { + tag: APIOptionalResultValues.Tag.Status, + param0: true, + param1: null, + param2: "Partial", + }; + const aor8 = { + tag: APIOptionalResultValues.Tag.Status, + param0: null, + param1: null, + param2: "Zero", + }; + const aor9 = { + tag: APIOptionalResultValues.Tag.Status, + param0: false, + param1: 500, + param2: null, + }; + const aor10 = { + tag: APIOptionalResultValues.Tag.Status, + param0: null, + param1: 0, + param2: "Zero", + }; assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor1), aor1); assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor2), aor2); @@ -168,77 +250,206 @@ export function runJsOptionalSupportTests(exports) { assert.equal(exports.roundTripOptionalAPIOptionalResult(null), null); // Optional TypedPayloadResult roundtrip - const tpr_precision = { tag: exports.TypedPayloadResult.Tag.Precision, param0: Math.fround(0.1) }; - assert.deepEqual(exports.roundTripOptionalTypedPayloadResult(tpr_precision), tpr_precision); - const tpr_direction = { tag: exports.TypedPayloadResult.Tag.Direction, param0: exports.Direction.North }; - assert.deepEqual(exports.roundTripOptionalTypedPayloadResult(tpr_direction), tpr_direction); - const tpr_optPrecisionSome = { tag: exports.TypedPayloadResult.Tag.OptPrecision, param0: Math.fround(0.001) }; - assert.deepEqual(exports.roundTripOptionalTypedPayloadResult(tpr_optPrecisionSome), tpr_optPrecisionSome); - const tpr_optPrecisionNull = { tag: exports.TypedPayloadResult.Tag.OptPrecision, param0: null }; - assert.deepEqual(exports.roundTripOptionalTypedPayloadResult(tpr_optPrecisionNull), tpr_optPrecisionNull); + const tpr_precision = { + tag: exports.TypedPayloadResult.Tag.Precision, + param0: Math.fround(0.1), + }; + assert.deepEqual( + exports.roundTripOptionalTypedPayloadResult(tpr_precision), + tpr_precision, + ); + const tpr_direction = { + tag: exports.TypedPayloadResult.Tag.Direction, + param0: exports.Direction.North, + }; + assert.deepEqual( + exports.roundTripOptionalTypedPayloadResult(tpr_direction), + tpr_direction, + ); + const tpr_optPrecisionSome = { + tag: exports.TypedPayloadResult.Tag.OptPrecision, + param0: Math.fround(0.001), + }; + assert.deepEqual( + exports.roundTripOptionalTypedPayloadResult(tpr_optPrecisionSome), + tpr_optPrecisionSome, + ); + const tpr_optPrecisionNull = { + tag: exports.TypedPayloadResult.Tag.OptPrecision, + param0: null, + }; + assert.deepEqual( + exports.roundTripOptionalTypedPayloadResult(tpr_optPrecisionNull), + tpr_optPrecisionNull, + ); const tpr_empty = { tag: exports.TypedPayloadResult.Tag.Empty }; - assert.deepEqual(exports.roundTripOptionalTypedPayloadResult(tpr_empty), tpr_empty); + assert.deepEqual( + exports.roundTripOptionalTypedPayloadResult(tpr_empty), + tpr_empty, + ); assert.equal(exports.roundTripOptionalTypedPayloadResult(null), null); // Optional AllTypesResult roundtrip - const atr_struct = { tag: AllTypesResultValues.Tag.StructPayload, param0: { street: "100 Main St", city: "Boston", zipCode: 2101 } }; - assert.deepEqual(exports.roundTripOptionalAllTypesResult(atr_struct), atr_struct); - const atr_array = { tag: AllTypesResultValues.Tag.ArrayPayload, param0: [10, 20, 30] }; - assert.deepEqual(exports.roundTripOptionalAllTypesResult(atr_array), atr_array); + const atr_struct = { + tag: AllTypesResultValues.Tag.StructPayload, + param0: { street: "100 Main St", city: "Boston", zipCode: 2101 }, + }; + assert.deepEqual( + exports.roundTripOptionalAllTypesResult(atr_struct), + atr_struct, + ); + const atr_array = { + tag: AllTypesResultValues.Tag.ArrayPayload, + param0: [10, 20, 30], + }; + assert.deepEqual( + exports.roundTripOptionalAllTypesResult(atr_array), + atr_array, + ); const atr_empty = { tag: AllTypesResultValues.Tag.Empty }; - assert.deepEqual(exports.roundTripOptionalAllTypesResult(atr_empty), atr_empty); + assert.deepEqual( + exports.roundTripOptionalAllTypesResult(atr_empty), + atr_empty, + ); assert.equal(exports.roundTripOptionalAllTypesResult(null), null); // OptionalAllTypesResult — optional struct, class, JSObject, nested enum, array as associated value payloads - const oatr_structSome = { tag: OptionalAllTypesResultValues.Tag.OptStruct, param0: { street: "200 Oak St", city: "Denver", zipCode: null } }; - assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_structSome), oatr_structSome); - - const oatr_structNone = { tag: OptionalAllTypesResultValues.Tag.OptStruct, param0: null }; - assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_structNone), oatr_structNone); - - const oatr_classSome = { tag: OptionalAllTypesResultValues.Tag.OptClass, param0: new exports.Greeter("OptEnumUser") }; - const oatr_classSome_result = exports.roundTripOptionalPayloadResult(oatr_classSome); - assert.equal(oatr_classSome_result.tag, OptionalAllTypesResultValues.Tag.OptClass); + const oatr_structSome = { + tag: OptionalAllTypesResultValues.Tag.OptStruct, + param0: { street: "200 Oak St", city: "Denver", zipCode: null }, + }; + assert.deepEqual( + exports.roundTripOptionalPayloadResult(oatr_structSome), + oatr_structSome, + ); + + const oatr_structNone = { + tag: OptionalAllTypesResultValues.Tag.OptStruct, + param0: null, + }; + assert.deepEqual( + exports.roundTripOptionalPayloadResult(oatr_structNone), + oatr_structNone, + ); + + const oatr_classSome = { + tag: OptionalAllTypesResultValues.Tag.OptClass, + param0: new exports.Greeter("OptEnumUser"), + }; + const oatr_classSome_result = + exports.roundTripOptionalPayloadResult(oatr_classSome); + assert.equal( + oatr_classSome_result.tag, + OptionalAllTypesResultValues.Tag.OptClass, + ); assert.equal(oatr_classSome_result.param0.name, "OptEnumUser"); - const oatr_classNone = { tag: OptionalAllTypesResultValues.Tag.OptClass, param0: null }; - assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_classNone), oatr_classNone); - - const oatr_jsObjectSome = { tag: OptionalAllTypesResultValues.Tag.OptJSObject, param0: { key: "value" } }; - const oatr_jsObjectSome_result = exports.roundTripOptionalPayloadResult(oatr_jsObjectSome); - assert.equal(oatr_jsObjectSome_result.tag, OptionalAllTypesResultValues.Tag.OptJSObject); + const oatr_classNone = { + tag: OptionalAllTypesResultValues.Tag.OptClass, + param0: null, + }; + assert.deepEqual( + exports.roundTripOptionalPayloadResult(oatr_classNone), + oatr_classNone, + ); + + const oatr_jsObjectSome = { + tag: OptionalAllTypesResultValues.Tag.OptJSObject, + param0: { key: "value" }, + }; + const oatr_jsObjectSome_result = + exports.roundTripOptionalPayloadResult(oatr_jsObjectSome); + assert.equal( + oatr_jsObjectSome_result.tag, + OptionalAllTypesResultValues.Tag.OptJSObject, + ); assert.equal(oatr_jsObjectSome_result.param0.key, "value"); - const oatr_jsObjectNone = { tag: OptionalAllTypesResultValues.Tag.OptJSObject, param0: null }; - assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_jsObjectNone), oatr_jsObjectNone); - - const oatr_nestedEnumSome = { tag: OptionalAllTypesResultValues.Tag.OptNestedEnum, param0: { tag: APIResultValues.Tag.Failure, param0: 404 } }; - assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_nestedEnumSome), oatr_nestedEnumSome); - - const oatr_nestedEnumNone = { tag: OptionalAllTypesResultValues.Tag.OptNestedEnum, param0: null }; - assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_nestedEnumNone), oatr_nestedEnumNone); - - const oatr_arraySome = { tag: OptionalAllTypesResultValues.Tag.OptArray, param0: [1, 2, 3] }; - assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_arraySome), oatr_arraySome); - - const oatr_arrayNone = { tag: OptionalAllTypesResultValues.Tag.OptArray, param0: null }; - assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_arrayNone), oatr_arrayNone); - - const oatr_jsClassSome = { tag: OptionalAllTypesResultValues.Tag.OptJsClass, param0: new ImportedFoo("optEnumFoo") }; - const oatr_jsClassSome_result = exports.roundTripOptionalPayloadResult(oatr_jsClassSome); - assert.equal(oatr_jsClassSome_result.tag, OptionalAllTypesResultValues.Tag.OptJsClass); + const oatr_jsObjectNone = { + tag: OptionalAllTypesResultValues.Tag.OptJSObject, + param0: null, + }; + assert.deepEqual( + exports.roundTripOptionalPayloadResult(oatr_jsObjectNone), + oatr_jsObjectNone, + ); + + const oatr_nestedEnumSome = { + tag: OptionalAllTypesResultValues.Tag.OptNestedEnum, + param0: { tag: APIResultValues.Tag.Failure, param0: 404 }, + }; + assert.deepEqual( + exports.roundTripOptionalPayloadResult(oatr_nestedEnumSome), + oatr_nestedEnumSome, + ); + + const oatr_nestedEnumNone = { + tag: OptionalAllTypesResultValues.Tag.OptNestedEnum, + param0: null, + }; + assert.deepEqual( + exports.roundTripOptionalPayloadResult(oatr_nestedEnumNone), + oatr_nestedEnumNone, + ); + + const oatr_arraySome = { + tag: OptionalAllTypesResultValues.Tag.OptArray, + param0: [1, 2, 3], + }; + assert.deepEqual( + exports.roundTripOptionalPayloadResult(oatr_arraySome), + oatr_arraySome, + ); + + const oatr_arrayNone = { + tag: OptionalAllTypesResultValues.Tag.OptArray, + param0: null, + }; + assert.deepEqual( + exports.roundTripOptionalPayloadResult(oatr_arrayNone), + oatr_arrayNone, + ); + + const oatr_jsClassSome = { + tag: OptionalAllTypesResultValues.Tag.OptJsClass, + param0: new ImportedFoo("optEnumFoo"), + }; + const oatr_jsClassSome_result = + exports.roundTripOptionalPayloadResult(oatr_jsClassSome); + assert.equal( + oatr_jsClassSome_result.tag, + OptionalAllTypesResultValues.Tag.OptJsClass, + ); assert.equal(oatr_jsClassSome_result.param0.value, "optEnumFoo"); - const oatr_jsClassNone = { tag: OptionalAllTypesResultValues.Tag.OptJsClass, param0: null }; - assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_jsClassNone), oatr_jsClassNone); + const oatr_jsClassNone = { + tag: OptionalAllTypesResultValues.Tag.OptJsClass, + param0: null, + }; + assert.deepEqual( + exports.roundTripOptionalPayloadResult(oatr_jsClassNone), + oatr_jsClassNone, + ); const oatr_empty = { tag: OptionalAllTypesResultValues.Tag.Empty }; - assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_empty), oatr_empty); + assert.deepEqual( + exports.roundTripOptionalPayloadResult(oatr_empty), + oatr_empty, + ); // Optional OptionalAllTypesResult roundtrip - assert.deepEqual(exports.roundTripOptionalPayloadResultOpt(oatr_structSome), oatr_structSome); - assert.deepEqual(exports.roundTripOptionalPayloadResultOpt(oatr_structNone), oatr_structNone); - assert.deepEqual(exports.roundTripOptionalPayloadResultOpt(oatr_empty), oatr_empty); + assert.deepEqual( + exports.roundTripOptionalPayloadResultOpt(oatr_structSome), + oatr_structSome, + ); + assert.deepEqual( + exports.roundTripOptionalPayloadResultOpt(oatr_structNone), + oatr_structNone, + ); + assert.deepEqual( + exports.roundTripOptionalPayloadResultOpt(oatr_empty), + oatr_empty, + ); assert.equal(exports.roundTripOptionalPayloadResultOpt(null), null); exports.takeOptionalJSObject(null);