diff --git a/Benchmarks/Sources/Generated/BridgeJS.ImportTS.swift b/Benchmarks/Sources/Generated/BridgeJS.ImportTS.swift index 871938cf..bc7f0b17 100644 --- a/Benchmarks/Sources/Generated/BridgeJS.ImportTS.swift +++ b/Benchmarks/Sources/Generated/BridgeJS.ImportTS.swift @@ -30,7 +30,7 @@ func benchmarkHelperNoopWithNumber(_ n: Double) throws(JSException) -> Void { fatalError("Only available on WebAssembly") } #endif - bjs_benchmarkHelperNoopWithNumber(n) + bjs_benchmarkHelperNoopWithNumber(n.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } @@ -45,11 +45,7 @@ func benchmarkRunner(_ name: String, _ body: JSObject) throws(JSException) -> Vo fatalError("Only available on WebAssembly") } #endif - var name = name - let nameId = name.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_benchmarkRunner(nameId, Int32(bitPattern: body.id)) + bjs_benchmarkRunner(name.bridgeJSLowerParameter(), body.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/BridgeJSUtilities b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/BridgeJSUtilities new file mode 120000 index 00000000..a43f43e2 --- /dev/null +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/BridgeJSUtilities @@ -0,0 +1 @@ +../../../../Plugins/BridgeJS/Sources/BridgeJSUtilities \ No newline at end of file diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.ExportSwift.swift b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.ExportSwift.swift index 3936b254..9e4515f5 100644 --- a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.ExportSwift.swift +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.ExportSwift.swift @@ -11,7 +11,7 @@ public func _bjs_PlayBridgeJS_init() -> UnsafeMutableRawPointer { #if arch(wasm32) let ret = PlayBridgeJS() - return Unmanaged.passRetained(ret).toOpaque() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -19,19 +19,11 @@ public func _bjs_PlayBridgeJS_init() -> UnsafeMutableRawPointer { @_expose(wasm, "bjs_PlayBridgeJS_update") @_cdecl("bjs_PlayBridgeJS_update") -public func _bjs_PlayBridgeJS_update(_self: UnsafeMutableRawPointer, swiftSourceBytes: Int32, swiftSourceLen: Int32, dtsSourceBytes: Int32, dtsSourceLen: Int32) -> UnsafeMutableRawPointer { +public func _bjs_PlayBridgeJS_update(_self: UnsafeMutableRawPointer, swiftSourceBytes: Int32, swiftSourceLength: Int32, dtsSourceBytes: Int32, dtsSourceLength: Int32) -> UnsafeMutableRawPointer { #if arch(wasm32) do { - let swiftSource = String(unsafeUninitializedCapacity: Int(swiftSourceLen)) { b in - _swift_js_init_memory(swiftSourceBytes, b.baseAddress.unsafelyUnwrapped) - return Int(swiftSourceLen) - } - let dtsSource = String(unsafeUninitializedCapacity: Int(dtsSourceLen)) { b in - _swift_js_init_memory(dtsSourceBytes, b.baseAddress.unsafelyUnwrapped) - return Int(dtsSourceLen) - } - let ret = try Unmanaged.fromOpaque(_self).takeUnretainedValue().update(swiftSource: swiftSource, dtsSource: dtsSource) - return Unmanaged.passRetained(ret).toOpaque() + let ret = try PlayBridgeJS.bridgeJSLiftParameter(_self).update(swiftSource: String.bridgeJSLiftParameter(swiftSourceBytes, swiftSourceLength), dtsSource: String.bridgeJSLiftParameter(dtsSourceBytes, dtsSourceLength)) + return ret.bridgeJSLowerReturn() } catch let error { if let error = error.thrownValue.object { withExtendedLifetime(error) { @@ -56,10 +48,16 @@ public func _bjs_PlayBridgeJS_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension PlayBridgeJS: ConvertibleToJSValue { +extension PlayBridgeJS: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "PlayBridgeJS", name: "bjs_PlayBridgeJS_wrap") func _bjs_PlayBridgeJS_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_PlayBridgeJS_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_PlayBridgeJS_wrap(Unmanaged.passRetained(self).toOpaque())))) } } @@ -68,10 +66,8 @@ extension PlayBridgeJS: ConvertibleToJSValue { @_cdecl("bjs_PlayBridgeJSOutput_outputJs") public func _bjs_PlayBridgeJSOutput_outputJs(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().outputJs() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = PlayBridgeJSOutput.bridgeJSLiftParameter(_self).outputJs() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -81,10 +77,8 @@ public func _bjs_PlayBridgeJSOutput_outputJs(_self: UnsafeMutableRawPointer) -> @_cdecl("bjs_PlayBridgeJSOutput_outputDts") public func _bjs_PlayBridgeJSOutput_outputDts(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().outputDts() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = PlayBridgeJSOutput.bridgeJSLiftParameter(_self).outputDts() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -94,10 +88,8 @@ public func _bjs_PlayBridgeJSOutput_outputDts(_self: UnsafeMutableRawPointer) -> @_cdecl("bjs_PlayBridgeJSOutput_importSwiftGlue") public func _bjs_PlayBridgeJSOutput_importSwiftGlue(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().importSwiftGlue() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = PlayBridgeJSOutput.bridgeJSLiftParameter(_self).importSwiftGlue() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -107,10 +99,8 @@ public func _bjs_PlayBridgeJSOutput_importSwiftGlue(_self: UnsafeMutableRawPoint @_cdecl("bjs_PlayBridgeJSOutput_exportSwiftGlue") public func _bjs_PlayBridgeJSOutput_exportSwiftGlue(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().exportSwiftGlue() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = PlayBridgeJSOutput.bridgeJSLiftParameter(_self).exportSwiftGlue() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -122,10 +112,16 @@ public func _bjs_PlayBridgeJSOutput_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension PlayBridgeJSOutput: ConvertibleToJSValue { +extension PlayBridgeJSOutput: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "PlayBridgeJS", name: "bjs_PlayBridgeJSOutput_wrap") func _bjs_PlayBridgeJSOutput_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_PlayBridgeJSOutput_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_PlayBridgeJSOutput_wrap(Unmanaged.passRetained(self).toOpaque())))) } } \ No newline at end of file diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.ImportTS.swift b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.ImportTS.swift index 5d82db08..4d35ef74 100644 --- a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.ImportTS.swift +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.ImportTS.swift @@ -19,18 +19,14 @@ func createTS2Skeleton() throws(JSException) -> TS2Skeleton { if let error = _swift_js_take_exception() { throw error } - return TS2Skeleton(takingThis: ret) + return TS2Skeleton.bridgeJSLiftReturn(ret) } -struct TS2Skeleton { - let this: JSObject +struct TS2Skeleton: _JSBridgedClass { + let jsObject: JSObject - init(this: JSObject) { - self.this = this - } - - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject } func convert(_ ts: String) throws(JSException) -> String { @@ -42,18 +38,11 @@ struct TS2Skeleton { fatalError("Only available on WebAssembly") } #endif - var ts = ts - let tsId = ts.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_TS2Skeleton_convert(Int32(bitPattern: self.this.id), tsId) + let ret = bjs_TS2Skeleton_convert(self.bridgeJSLowerParameter(), ts.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } + return String.bridgeJSLiftReturn(ret) } } \ No newline at end of file diff --git a/Plugins/BridgeJS/Package.swift b/Plugins/BridgeJS/Package.swift index 9ac96d95..bb7daac2 100644 --- a/Plugins/BridgeJS/Package.swift +++ b/Plugins/BridgeJS/Package.swift @@ -29,6 +29,7 @@ let package = Package( name: "BridgeJSCore", dependencies: [ "BridgeJSSkeleton", + "BridgeJSUtilities", .product(name: "SwiftParser", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftBasicFormat", package: "swift-syntax"), @@ -36,10 +37,14 @@ let package = Package( ] ), .target(name: "BridgeJSSkeleton"), + .target(name: "BridgeJSUtilities"), .target( name: "BridgeJSLink", - dependencies: ["BridgeJSSkeleton"] + dependencies: [ + "BridgeJSSkeleton", + "BridgeJSUtilities", + ] ), .testTarget( diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index 56e01290..76ce16d6 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -4,6 +4,9 @@ import SwiftSyntaxBuilder #if canImport(BridgeJSSkeleton) import BridgeJSSkeleton #endif +#if canImport(BridgeJSUtilities) +import BridgeJSUtilities +#endif /// Exports Swift functions and classes to JavaScript /// @@ -51,7 +54,7 @@ public class ExportSwift { /// - Returns: A tuple containing the generated Swift code and a skeleton /// describing the exported APIs public func finalize() throws -> (outputSwift: String, outputSkeleton: ExportedSkeleton)? { - guard let outputSwift = renderSwiftGlue() else { + guard let outputSwift = try renderSwiftGlue() else { return nil } return ( @@ -334,7 +337,7 @@ public class ExportSwift { override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind { guard node.attributes.hasJSAttribute() else { return .skipChildren } - guard case .classBody(let className, let classKey) = state else { + guard case .classBody(_, let classKey) = state else { diagnose(node: node, message: "@JS var must be inside a @JS class") return .skipChildren } @@ -710,22 +713,26 @@ public class ExportSwift { @_spi(BridgeJS) import JavaScriptKit """ - func renderSwiftGlue() -> String? { + func renderSwiftGlue() throws -> String? { var decls: [DeclSyntax] = [] guard exportedFunctions.count > 0 || exportedClasses.count > 0 || exportedEnums.count > 0 else { return nil } decls.append(Self.prelude) - for enumDef in exportedEnums where enumDef.enumType == .simple { - decls.append(renderCaseEnumHelpers(enumDef)) + for enumDef in exportedEnums { + if enumDef.enumType == .simple { + decls.append(renderCaseEnumHelpers(enumDef)) + } else { + decls.append("extension \(raw: enumDef.swiftCallName): _BridgedSwiftEnumNoPayload {}") + } } for function in exportedFunctions { - decls.append(renderSingleExportedFunction(function: function)) + decls.append(try renderSingleExportedFunction(function: function)) } for klass in exportedClasses { - decls.append(contentsOf: renderSingleExportedClass(klass: klass)) + decls.append(contentsOf: try renderSingleExportedClass(klass: klass)) } let format = BasicFormat() return decls.map { $0.formatted(using: format).description }.joined(separator: "\n\n") @@ -746,11 +753,24 @@ public class ExportSwift { return """ extension \(raw: typeName) { - init?(bridgeJSRawValue: Int32) { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> \(raw: typeName) { + return \(raw: typeName)(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> \(raw: typeName) { + return \(raw: typeName)(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSRawValue + } + + private init?(bridgeJSRawValue: Int32) { \(raw: initSwitch) } - var bridgeJSRawValue: Int32 { + private var bridgeJSRawValue: Int32 { \(raw: valueSwitch) } } @@ -778,91 +798,22 @@ public class ExportSwift { self.body.append(item) } - func liftParameter(param: Parameter) { + func liftParameter(param: Parameter) throws { parameters.append(param) - switch param.type { - case .bool: - liftedParameterExprs.append(ExprSyntax("\(raw: param.name) == 1")) - abiParameterSignatures.append((param.name, .i32)) - case .int: - liftedParameterExprs.append(ExprSyntax("\(raw: param.type.swiftType)(\(raw: param.name))")) - abiParameterSignatures.append((param.name, .i32)) - case .float: - liftedParameterExprs.append(ExprSyntax("\(raw: param.name)")) - abiParameterSignatures.append((param.name, .f32)) - case .double: - liftedParameterExprs.append(ExprSyntax("\(raw: param.name)")) - abiParameterSignatures.append((param.name, .f64)) - case .string: - let bytesLabel = "\(param.name)Bytes" - let lengthLabel = "\(param.name)Len" - let prepare: CodeBlockItemSyntax = """ - let \(raw: param.name) = String(unsafeUninitializedCapacity: Int(\(raw: lengthLabel))) { b in - _swift_js_init_memory(\(raw: bytesLabel), b.baseAddress.unsafelyUnwrapped) - return Int(\(raw: lengthLabel)) - } - """ - append(prepare) - liftedParameterExprs.append(ExprSyntax("\(raw: param.name)")) - abiParameterSignatures.append((bytesLabel, .i32)) - abiParameterSignatures.append((lengthLabel, .i32)) - case .caseEnum(let enumName): - liftedParameterExprs.append(ExprSyntax("\(raw: enumName)(bridgeJSRawValue: \(raw: param.name))!")) - abiParameterSignatures.append((param.name, .i32)) - case .rawValueEnum(let enumName, let rawType): - if rawType == .string { - let bytesLabel = "\(param.name)Bytes" - let lengthLabel = "\(param.name)Len" - let prepare: CodeBlockItemSyntax = """ - let \(raw: param.name) = String(unsafeUninitializedCapacity: Int(\(raw: lengthLabel))) { b in - _swift_js_init_memory(\(raw: bytesLabel), b.baseAddress.unsafelyUnwrapped) - return Int(\(raw: lengthLabel)) - } - """ - append(prepare) - liftedParameterExprs.append(ExprSyntax("\(raw: enumName)(rawValue: \(raw: param.name))!")) - abiParameterSignatures.append((bytesLabel, .i32)) - abiParameterSignatures.append((lengthLabel, .i32)) - } else { - let conversionExpr: String - switch rawType { - case .bool: - conversionExpr = "\(enumName)(rawValue: \(param.name) != 0)!" - case .uint, .uint32, .uint64: - if rawType == .uint64 { - conversionExpr = - "\(enumName)(rawValue: \(rawType.rawValue)(bitPattern: Int64(\(param.name))))!" - } else { - conversionExpr = "\(enumName)(rawValue: \(rawType.rawValue)(bitPattern: \(param.name)))!" - } - default: - conversionExpr = "\(enumName)(rawValue: \(rawType.rawValue)(\(param.name)))!" - } - - liftedParameterExprs.append(ExprSyntax(stringLiteral: conversionExpr)) - if let wasmType = rawType.wasmCoreType { - abiParameterSignatures.append((param.name, wasmType)) - } - } - case .associatedValueEnum(_): - break - case .namespaceEnum: - break - case .jsObject(nil): - liftedParameterExprs.append(ExprSyntax("JSObject(id: UInt32(bitPattern: \(raw: param.name)))")) - abiParameterSignatures.append((param.name, .i32)) - case .jsObject(let name): - liftedParameterExprs.append( - ExprSyntax("\(raw: name)(takingThis: UInt32(bitPattern: \(raw: param.name)))") + let liftingInfo = try param.type.liftParameterInfo() + let argumentsToLift: [String] + if liftingInfo.parameters.count == 1 { + argumentsToLift = [param.name] + } else { + argumentsToLift = liftingInfo.parameters.map { (name, _) in param.name + name.capitalizedFirstLetter } + } + liftedParameterExprs.append( + ExprSyntax( + "\(raw: param.type.swiftType).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" ) - abiParameterSignatures.append((param.name, .i32)) - case .swiftHeapObject: - let objectExpr: ExprSyntax = - "Unmanaged<\(raw: param.type.swiftType)>.fromOpaque(\(raw: param.name)).takeUnretainedValue()" - liftedParameterExprs.append(objectExpr) - abiParameterSignatures.append((param.name, .pointer)) - case .void: - break + ) + for (name, type) in zip(argumentsToLift, liftingInfo.parameters.map { $0.type }) { + abiParameterSignatures.append((name, type)) } } @@ -896,16 +847,10 @@ public class ExportSwift { return CodeBlockItemSyntax(item: .init(StmtSyntax("return \(raw: callExpr).jsValue"))) } - let retMutability: String - if returnType == .string { - retMutability = "var" - } else { - retMutability = "let" - } if returnType == .void { return CodeBlockItemSyntax(item: .init(ExpressionStmtSyntax(expression: callExpr))) } else { - return CodeBlockItemSyntax(item: .init(DeclSyntax("\(raw: retMutability) ret = \(raw: callExpr)"))) + return CodeBlockItemSyntax(item: .init(DeclSyntax("let ret = \(raw: callExpr)"))) } } @@ -925,11 +870,10 @@ public class ExportSwift { func callPropertyGetter(klassName: String, propertyName: String, returnType: BridgeType) { let (_, selfExpr) = removeFirstLiftedParameter() - let retMutability = returnType == .string ? "var" : "let" if returnType == .void { append("\(raw: selfExpr).\(raw: propertyName)") } else { - append("\(raw: retMutability) ret = \(raw: selfExpr).\(raw: propertyName)") + append("let ret = \(raw: selfExpr).\(raw: propertyName)") } } @@ -939,116 +883,28 @@ public class ExportSwift { append("\(raw: selfExpr).\(raw: propertyName) = \(raw: newValueExpr)") } - func lowerReturnValue(returnType: BridgeType) { + func lowerReturnValue(returnType: BridgeType) throws { if effects.isAsync { // Async functions always return a Promise, which is a JSObject - _lowerReturnValue(returnType: .jsObject(nil)) + try _lowerReturnValue(returnType: .jsObject(nil)) } else { - _lowerReturnValue(returnType: returnType) + try _lowerReturnValue(returnType: returnType) } } - private func _lowerReturnValue(returnType: BridgeType) { - switch returnType { - case .void: - abiReturnType = nil - case .bool: - abiReturnType = .i32 - case .int: - abiReturnType = .i32 - case .float: - abiReturnType = .f32 - case .double: - abiReturnType = .f64 - case .string: - abiReturnType = nil - case .jsObject: - abiReturnType = .i32 - case .swiftHeapObject: - // UnsafeMutableRawPointer is returned as an i32 pointer - abiReturnType = .pointer - case .caseEnum: - abiReturnType = .i32 - case .rawValueEnum(_, let rawType): - abiReturnType = rawType == .string ? nil : rawType.wasmCoreType - case .associatedValueEnum: - abiReturnType = nil - case .namespaceEnum: - abiReturnType = nil + private func _lowerReturnValue(returnType: BridgeType) throws { + let loweringInfo = try returnType.loweringReturnInfo() + abiReturnType = loweringInfo.returnType + if returnType == .void { + return } - if effects.isAsync { // The return value of async function (T of `(...) async -> T`) is // handled by the JSPromise.async, so we don't need to do anything here. return } - switch returnType { - case .void: break - case .int, .float, .double: - append("return \(raw: abiReturnType!.swiftType)(ret)") - case .bool: - append("return Int32(ret ? 1 : 0)") - case .string: - append( - """ - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - """ - ) - case .caseEnum: - abiReturnType = .i32 - append("return ret.bridgeJSRawValue") - case .rawValueEnum(_, let rawType): - if rawType == .string { - append( - """ - var rawValue = ret.rawValue - return rawValue.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - """ - ) - } else { - switch rawType { - case .bool: - append("return Int32(ret.rawValue ? 1 : 0)") - case .int, .int32, .uint, .uint32: - append("return Int32(ret.rawValue)") - case .int64, .uint64: - append("return Int64(ret.rawValue)") - case .float: - append("return Float32(ret.rawValue)") - case .double: - append("return Float64(ret.rawValue)") - default: - append("return Int32(ret.rawValue)") - } - } - case .associatedValueEnum: break; - case .namespaceEnum: break; - case .jsObject(nil): - append( - """ - return _swift_js_retain(Int32(bitPattern: ret.id)) - """ - ) - case .jsObject(_?): - append( - """ - return _swift_js_retain(Int32(bitPattern: ret.this.id)) - """ - ) - case .swiftHeapObject: - // Perform a manual retain on the object, which will be balanced by a - // release called via FinalizationRegistry - append( - """ - return Unmanaged.passRetained(ret).toOpaque() - """ - ) - } + append("return ret.bridgeJSLowerReturn()") } func render(abiName: String) -> DeclSyntax { @@ -1058,7 +914,7 @@ public class ExportSwift { let ret = JSPromise.async { \(CodeBlockItemListSyntax(self.body)) }.jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() """ } else if effects.isThrows { body = """ @@ -1118,13 +974,13 @@ public class ExportSwift { } } - func renderSingleExportedFunction(function: ExportedFunction) -> DeclSyntax { + func renderSingleExportedFunction(function: ExportedFunction) throws -> DeclSyntax { let builder = ExportedThunkBuilder(effects: function.effects) for param in function.parameters { - builder.liftParameter(param: param) + try builder.liftParameter(param: param) } builder.call(name: function.name, returnType: function.returnType) - builder.lowerReturnValue(returnType: function.returnType) + try builder.lowerReturnValue(returnType: function.returnType) return builder.render(abiName: function.abiName) } @@ -1175,32 +1031,32 @@ public class ExportSwift { /// Unmanaged.fromOpaque(pointer).release() /// } /// ``` - func renderSingleExportedClass(klass: ExportedClass) -> [DeclSyntax] { + func renderSingleExportedClass(klass: ExportedClass) throws -> [DeclSyntax] { var decls: [DeclSyntax] = [] if let constructor = klass.constructor { let builder = ExportedThunkBuilder(effects: constructor.effects) for param in constructor.parameters { - builder.liftParameter(param: param) + try builder.liftParameter(param: param) } builder.call(name: klass.swiftCallName, returnType: BridgeType.swiftHeapObject(klass.name)) - builder.lowerReturnValue(returnType: BridgeType.swiftHeapObject(klass.name)) + try builder.lowerReturnValue(returnType: BridgeType.swiftHeapObject(klass.name)) decls.append(builder.render(abiName: constructor.abiName)) } for method in klass.methods { let builder = ExportedThunkBuilder(effects: method.effects) - builder.liftParameter( + try builder.liftParameter( param: Parameter(label: nil, name: "_self", type: BridgeType.swiftHeapObject(klass.swiftCallName)) ) for param in method.parameters { - builder.liftParameter(param: param) + try builder.liftParameter(param: param) } builder.callMethod( klassName: klass.swiftCallName, methodName: method.name, returnType: method.returnType ) - builder.lowerReturnValue(returnType: method.returnType) + try builder.lowerReturnValue(returnType: method.returnType) decls.append(builder.render(abiName: method.abiName)) } @@ -1208,7 +1064,7 @@ public class ExportSwift { for property in klass.properties { // Generate getter let getterBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false)) - getterBuilder.liftParameter( + try getterBuilder.liftParameter( param: Parameter(label: nil, name: "_self", type: .swiftHeapObject(klass.name)) ) getterBuilder.callPropertyGetter( @@ -1216,23 +1072,23 @@ public class ExportSwift { propertyName: property.name, returnType: property.type ) - getterBuilder.lowerReturnValue(returnType: property.type) + try getterBuilder.lowerReturnValue(returnType: property.type) decls.append(getterBuilder.render(abiName: property.getterAbiName(className: klass.name))) // Generate setter if property is not readonly if !property.isReadonly { let setterBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false)) - setterBuilder.liftParameter( + try setterBuilder.liftParameter( param: Parameter(label: nil, name: "_self", type: .swiftHeapObject(klass.name)) ) - setterBuilder.liftParameter( + try setterBuilder.liftParameter( param: Parameter(label: "value", name: "value", type: property.type) ) setterBuilder.callPropertySetter( klassName: klass.name, propertyName: property.name ) - setterBuilder.lowerReturnValue(returnType: .void) + try setterBuilder.lowerReturnValue(returnType: .void) decls.append(setterBuilder.render(abiName: property.setterAbiName(className: klass.name))) } } @@ -1262,7 +1118,7 @@ public class ExportSwift { /// For a class named `Greeter`, this generates: /// /// ```swift - /// extension Greeter: ConvertibleToJSValue { + /// extension Greeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { /// var jsValue: JSValue { /// @_extern(wasm, module: "MyModule", name: "bjs_Greeter_wrap") /// func _bjs_Greeter_wrap(_: UnsafeMutableRawPointer) -> Int32 @@ -1275,10 +1131,16 @@ public class ExportSwift { let externFunctionName = "bjs_\(klass.name)_wrap" return """ - extension \(raw: klass.swiftCallName): ConvertibleToJSValue { + extension \(raw: klass.swiftCallName): ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "\(raw: moduleName)", name: "\(raw: externFunctionName)") func \(raw: wrapFunctionName)(_: UnsafeMutableRawPointer) -> Int32 + #else + func \(raw: wrapFunctionName)(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: \(raw: wrapFunctionName)(Unmanaged.passRetained(self).toOpaque())))) } } @@ -1355,4 +1217,95 @@ extension BridgeType { case .namespaceEnum(let name): return name } } + + 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 swiftHeapObject = LiftingIntrinsicInfo(parameters: [("value", .pointer)]) + static let void = LiftingIntrinsicInfo(parameters: []) + static let caseEnum = LiftingIntrinsicInfo(parameters: [("value", .i32)]) + } + + func liftParameterInfo() throws -> LiftingIntrinsicInfo { + switch self { + case .bool: return .bool + case .int: return .int + case .float: return .float + case .double: return .double + case .string: return .string + case .jsObject: return .jsObject + case .swiftHeapObject: return .swiftHeapObject + case .void: return .void + case .caseEnum: return .caseEnum + case .rawValueEnum(_, let rawType): + switch rawType { + case .bool: return .bool + case .int: return .int + case .float: return .float + case .double: return .double + case .string: return .string + case .int32: return .int + case .int64: return .int + case .uint: return .int + case .uint32: return .int + case .uint64: return .int + } + case .associatedValueEnum: + throw BridgeJSCoreError("Associated value enums are not supported to pass as parameters") + case .namespaceEnum: + throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters") + } + } + + 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 swiftHeapObject = LoweringIntrinsicInfo(returnType: .pointer) + static let void = LoweringIntrinsicInfo(returnType: nil) + static let caseEnum = LoweringIntrinsicInfo(returnType: .i32) + static let rawValueEnum = LoweringIntrinsicInfo(returnType: .i32) + } + + func loweringReturnInfo() throws -> LoweringIntrinsicInfo { + switch self { + case .bool: return .bool + case .int: return .int + case .float: return .float + case .double: return .double + case .string: return .string + case .jsObject: return .jsObject + case .swiftHeapObject: return .swiftHeapObject + case .void: return .void + case .caseEnum: return .caseEnum + case .rawValueEnum(_, let rawType): + switch rawType { + case .bool: return .bool + case .int: return .int + case .float: return .float + case .double: return .double + case .string: return .string + case .int32: return .int + case .int64: return .int + case .uint: return .int + case .uint32: return .int + case .uint64: return .int + } + case .associatedValueEnum: + throw BridgeJSCoreError("Associated value enums are not supported to pass as parameters") + case .namespaceEnum: + throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters") + } + } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift index bcbae469..148157d3 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift @@ -4,6 +4,9 @@ import SwiftSyntaxBuilder #if canImport(BridgeJSSkeleton) import BridgeJSSkeleton #endif +#if canImport(BridgeJSUtilities) +import BridgeJSUtilities +#endif /// Imports TypeScript declarations and generates Swift bridge code /// @@ -68,84 +71,19 @@ public struct ImportTS { } func lowerParameter(param: Parameter) throws { - switch param.type { - case .bool: - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("Int32(\(raw: param.name) ? 1 : 0)") - ) - ) - abiParameterSignatures.append((param.name, .i32)) - case .int: - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("\(raw: param.name)") - ) - ) - abiParameterSignatures.append((param.name, .i32)) - case .float: - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("\(raw: param.name)") - ) - ) - abiParameterSignatures.append((param.name, .f32)) - case .double: - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("\(raw: param.name)") - ) - ) - abiParameterSignatures.append((param.name, .f64)) - case .string: - let stringIdName = "\(param.name)Id" - body.append( - """ - var \(raw: param.name) = \(raw: param.name) - - """ - ) - body.append( - """ - let \(raw: stringIdName) = \(raw: param.name).withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - """ - ) - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("\(raw: stringIdName)") - ) - ) - abiParameterSignatures.append((param.name, .i32)) - case .caseEnum, .rawValueEnum, .associatedValueEnum, .namespaceEnum: - throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") - case .jsObject(_?): - abiParameterSignatures.append((param.name, .i32)) - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("Int32(bitPattern: \(raw: param.name).this.id)") - ) - ) - case .jsObject(nil): - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("Int32(bitPattern: \(raw: param.name).id)") - ) + let loweringInfo = try param.type.loweringParameterInfo() + assert( + loweringInfo.loweredParameters.count == 1, + "For now, we require a single parameter to be lowered to a single Wasm core type" + ) + let (_, type) = loweringInfo.loweredParameters[0] + abiParameterForwardings.append( + LabeledExprSyntax( + label: param.label, + expression: ExprSyntax("\(raw: param.name).bridgeJSLowerParameter()") ) - abiParameterSignatures.append((param.name, .i32)) - case .swiftHeapObject(_): - throw BridgeJSCoreError("swiftHeapObject is not supported in imported signatures") - case .void: - break - } + ) + abiParameterSignatures.append((param.name, type)) } func call(returnType: BridgeType) { @@ -160,43 +98,12 @@ public struct ImportTS { } func liftReturnValue(returnType: BridgeType) throws { - switch returnType { - case .bool: - abiReturnType = .i32 - body.append("return ret == 1") - case .int: - abiReturnType = .i32 - body.append("return \(raw: returnType.swiftType)(ret)") - case .float: - abiReturnType = .f32 - body.append("return \(raw: returnType.swiftType)(ret)") - case .double: - abiReturnType = .f64 - body.append("return \(raw: returnType.swiftType)(ret)") - case .string: - abiReturnType = .i32 - body.append( - """ - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } - """ - ) - case .caseEnum, .rawValueEnum, .associatedValueEnum, .namespaceEnum: - throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") - case .jsObject(let name): - abiReturnType = .i32 - if let name = name { - body.append("return \(raw: name)(takingThis: ret)") - } else { - body.append("return JSObject(id: UInt32(bitPattern: ret))") - } - case .swiftHeapObject(_): - throw BridgeJSCoreError("swiftHeapObject is not supported in imported signatures") - case .void: - break + let liftingInfo = try returnType.liftingReturnInfo() + abiReturnType = liftingInfo.valueToLift + if returnType == .void { + return } + body.append("return \(raw: returnType.swiftType).bridgeJSLiftReturn(ret)") } func assignThis(returnType: BridgeType) { @@ -204,7 +111,7 @@ public struct ImportTS { preconditionFailure("assignThis can only be called with a jsObject return type") } abiReturnType = .i32 - body.append("self.this = JSObject(id: UInt32(bitPattern: ret))") + body.append("self.jsObject = JSObject(id: UInt32(bitPattern: ret))") } func renderImportDecl() -> DeclSyntax { @@ -392,7 +299,7 @@ public struct ImportTS { try builder.lowerParameter(param: newValue) builder.call(returnType: .void) return builder.renderThunkDecl( - name: "set\(property.name.capitalizedFirstLetter())", + name: "set\(property.name.capitalizedFirstLetter)", parameters: [newValue], returnType: .void ) @@ -431,25 +338,22 @@ public struct ImportTS { let classDecl = try StructDeclSyntax( leadingTrivia: Self.renderDocumentation(documentation: type.documentation), name: .identifier(name), + inheritanceClause: InheritanceClauseSyntax( + inheritedTypesBuilder: { + InheritedTypeSyntax(type: TypeSyntax("_JSBridgedClass")) + } + ), memberBlockBuilder: { DeclSyntax( """ - let this: JSObject + let jsObject: JSObject """ ).with(\.trailingTrivia, .newlines(2)) DeclSyntax( """ - init(this: JSObject) { - self.this = this - } - """ - ).with(\.trailingTrivia, .newlines(2)) - - DeclSyntax( - """ - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject } """ ).with(\.trailingTrivia, .newlines(2)) @@ -505,9 +409,60 @@ public struct ImportTS { } } -fileprivate extension String { - func capitalizedFirstLetter() -> String { - guard !isEmpty else { return self } - return prefix(1).uppercased() + dropFirst() +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 void = LoweringParameterInfo(loweredParameters: []) + } + + func loweringParameterInfo() throws -> LoweringParameterInfo { + switch self { + case .bool: return .bool + case .int: return .int + case .float: return .float + case .double: return .double + case .string: return .string + case .jsObject: return .jsObject + case .void: return .void + case .swiftHeapObject: + throw BridgeJSCoreError("swiftHeapObject is not supported in imported signatures") + case .caseEnum, .rawValueEnum, .associatedValueEnum, .namespaceEnum: + throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") + } + } + + 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 void = LiftingReturnInfo(valueToLift: nil) + } + + func liftingReturnInfo() throws -> LiftingReturnInfo { + switch self { + case .bool: return .bool + case .int: return .int + case .float: return .float + case .double: return .double + case .string: return .string + case .jsObject: return .jsObject + case .void: return .void + case .swiftHeapObject: + throw BridgeJSCoreError("swiftHeapObject is not supported in imported signatures") + case .caseEnum, .rawValueEnum, .associatedValueEnum, .namespaceEnum: + throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") + } } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index 2b220e43..360a6274 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -3,6 +3,9 @@ import struct Foundation.Data #if canImport(BridgeJSSkeleton) import BridgeJSSkeleton #endif +#if canImport(BridgeJSUtilities) +import BridgeJSUtilities +#endif struct BridgeJSLink { /// The exported skeletons @@ -90,7 +93,7 @@ struct BridgeJSLink { for skeleton in exportedSkeletons { for klass in skeleton.classes { - let (jsType, dtsType, dtsExportEntry) = renderExportedClass(klass) + let (jsType, dtsType, dtsExportEntry) = try renderExportedClass(klass) classLines.append(contentsOf: jsType) exportsLines.append("\(klass.name),") dtsExportLines.append(contentsOf: dtsExportEntry) @@ -131,7 +134,7 @@ struct BridgeJSLink { } for function in skeleton.functions { - var (js, dts) = renderExportedFunction(function: function) + var (js, dts) = try renderExportedFunction(function: function) if function.namespace != nil { namespacedFunctions.append(function) @@ -222,16 +225,16 @@ struct BridgeJSLink { // To update this file, just rebuild your project or run // `swift package bridge-js`. - \(topLevelEnumsSection)\(namespaceAssignmentsSection)export async function createInstantiator(options, swift) { - let instance; - let memory; - let setException; - const textDecoder = new TextDecoder("utf-8"); - const textEncoder = new TextEncoder("utf-8"); + \(topLevelEnumsSection)\(namespaceAssignmentsSection)export async function createInstantiator(options, \(JSGlueVariableScope.reservedSwift)) { + let \(JSGlueVariableScope.reservedInstance); + let \(JSGlueVariableScope.reservedMemory); + let \(JSGlueVariableScope.reservedSetException); + const \(JSGlueVariableScope.reservedTextDecoder) = new TextDecoder("utf-8"); + const \(JSGlueVariableScope.reservedTextEncoder) = new TextEncoder("utf-8"); - let tmpRetString; - let tmpRetBytes; - let tmpRetException; + let \(JSGlueVariableScope.reservedStorageToReturnString); + let \(JSGlueVariableScope.reservedStorageToReturnBytes); + let \(JSGlueVariableScope.reservedStorageToReturnException); return { /** * @param {WebAssembly.Imports} importObject @@ -241,45 +244,45 @@ struct BridgeJSLink { importObject["bjs"] = bjs; const imports = options.getImports(importsContext); bjs["swift_js_return_string"] = function(ptr, len) { - const bytes = new Uint8Array(memory.buffer, ptr, len)\(sharedMemory ? ".slice()" : ""); - tmpRetString = textDecoder.decode(bytes); + const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr, len)\(sharedMemory ? ".slice()" : ""); + \(JSGlueVariableScope.reservedStorageToReturnString) = \(JSGlueVariableScope.reservedTextDecoder).decode(bytes); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { - const source = swift.memory.getObject(sourceId); - const bytes = new Uint8Array(memory.buffer, bytesPtr); + const source = \(JSGlueVariableScope.reservedSwift).memory.getObject(sourceId); + const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, bytesPtr); bytes.set(source); } bjs["swift_js_make_js_string"] = function(ptr, len) { - const bytes = new Uint8Array(memory.buffer, ptr, len)\(sharedMemory ? ".slice()" : ""); - return swift.memory.retain(textDecoder.decode(bytes)); + const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr, len)\(sharedMemory ? ".slice()" : ""); + return \(JSGlueVariableScope.reservedSwift).memory.retain(\(JSGlueVariableScope.reservedTextDecoder).decode(bytes)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { - const target = new Uint8Array(memory.buffer, ptr, len); - target.set(tmpRetBytes); - tmpRetBytes = undefined; + const target = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr, len); + target.set(\(JSGlueVariableScope.reservedStorageToReturnBytes)); + \(JSGlueVariableScope.reservedStorageToReturnBytes) = undefined; } bjs["swift_js_throw"] = function(id) { - tmpRetException = swift.memory.retainByRef(id); + \(JSGlueVariableScope.reservedStorageToReturnException) = \(JSGlueVariableScope.reservedSwift).memory.retainByRef(id); } bjs["swift_js_retain"] = function(id) { - return swift.memory.retainByRef(id); + return \(JSGlueVariableScope.reservedSwift).memory.retainByRef(id); } bjs["swift_js_release"] = function(id) { - swift.memory.release(id); + \(JSGlueVariableScope.reservedSwift).memory.release(id); } \(renderSwiftClassWrappers().map { $0.indent(count: 12) }.joined(separator: "\n")) \(importObjectBuilders.flatMap { $0.importedLines }.map { $0.indent(count: 12) }.joined(separator: "\n")) }, setInstance: (i) => { - instance = i; - memory = instance.exports.memory; - setException = (error) => { - instance.exports._swift_js_exception.value = swift.memory.retain(error) + \(JSGlueVariableScope.reservedInstance) = i; + \(JSGlueVariableScope.reservedMemory) = \(JSGlueVariableScope.reservedInstance).exports.memory; + \(JSGlueVariableScope.reservedSetException) = (error) => { + \(JSGlueVariableScope.reservedInstance).exports._swift_js_exception.value = \(JSGlueVariableScope.reservedSwift).memory.retain(error) } }, /** @param {WebAssembly.Instance} instance */ createExports: (instance) => { - const js = swift.memory.heap; + const js = \(JSGlueVariableScope.reservedSwift).memory.heap; \(exportsSection) } } @@ -343,7 +346,7 @@ struct BridgeJSLink { let wrapperFunctionName = "bjs_\(klass.name)_wrap" wrapperLines.append("importObject[\"\(moduleName)\"][\"\(wrapperFunctionName)\"] = function(pointer) {") wrapperLines.append(" const obj = \(klass.name).__construct(pointer);") - wrapperLines.append(" return swift.memory.retain(obj);") + wrapperLines.append(" return \(JSGlueVariableScope.reservedSwift).memory.retain(obj);") wrapperLines.append("};") } } @@ -384,125 +387,66 @@ struct BridgeJSLink { } class ExportedThunkBuilder { - var bodyLines: [String] = [] - var cleanupLines: [String] = [] + var body: CodeFragmentPrinter + var cleanupCode: CodeFragmentPrinter var parameterForwardings: [String] = [] let effects: Effects + let scope: JSGlueVariableScope init(effects: Effects) { self.effects = effects + self.scope = JSGlueVariableScope() + self.body = CodeFragmentPrinter() + self.cleanupCode = CodeFragmentPrinter() } - func lowerParameter(param: Parameter) { - switch param.type { - case .void: return - case .int, .float, .double, .bool: - parameterForwardings.append(param.name) - case .string: - let bytesLabel = "\(param.name)Bytes" - let bytesIdLabel = "\(param.name)Id" - bodyLines.append("const \(bytesLabel) = textEncoder.encode(\(param.name));") - bodyLines.append("const \(bytesIdLabel) = swift.memory.retain(\(bytesLabel));") - cleanupLines.append("swift.memory.release(\(bytesIdLabel));") - parameterForwardings.append(bytesIdLabel) - parameterForwardings.append("\(bytesLabel).length") - case .caseEnum(_): - parameterForwardings.append("\(param.name) | 0") - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - let bytesLabel = "\(param.name)Bytes" - let bytesIdLabel = "\(param.name)Id" - bodyLines.append("const \(bytesLabel) = textEncoder.encode(\(param.name));") - bodyLines.append("const \(bytesIdLabel) = swift.memory.retain(\(bytesLabel));") - cleanupLines.append("swift.memory.release(\(bytesIdLabel));") - parameterForwardings.append(bytesIdLabel) - parameterForwardings.append("\(bytesLabel).length") - case .bool: - parameterForwardings.append("\(param.name) ? 1 : 0") - default: - parameterForwardings.append("\(param.name)") - } - case .associatedValueEnum: - parameterForwardings.append("0") - parameterForwardings.append("0") - case .namespaceEnum: - break - case .jsObject: - parameterForwardings.append("swift.memory.retain(\(param.name))") - case .swiftHeapObject: - parameterForwardings.append("\(param.name).pointer") - } + func lowerParameter(param: Parameter) throws { + let loweringFragment = try IntrinsicJSFragment.lowerParameter(type: param.type) + assert( + loweringFragment.parameters.count == 1, + "Lowering fragment should have exactly one parameter to lower" + ) + let loweredValues = loweringFragment.printCode([param.name], scope, body, cleanupCode) + parameterForwardings.append(contentsOf: loweredValues) } func lowerSelf() { parameterForwardings.append("this.pointer") } - func call(abiName: String, returnType: BridgeType) -> String? { + func call(abiName: String, returnType: BridgeType) throws -> String? { if effects.isAsync { - return _call(abiName: abiName, returnType: .jsObject(nil)) + return try _call(abiName: abiName, returnType: .jsObject(nil)) } else { - return _call(abiName: abiName, returnType: returnType) + return try _call(abiName: abiName, returnType: returnType) } } - private func _call(abiName: String, returnType: BridgeType) -> String? { + private func _call(abiName: String, returnType: BridgeType) throws -> String? { let call = "instance.exports.\(abiName)(\(parameterForwardings.joined(separator: ", ")))" - var returnExpr: String? - - switch returnType { - case .void: - bodyLines.append("\(call);") - case .string: - bodyLines.append("\(call);") - bodyLines.append("const ret = tmpRetString;") - bodyLines.append("tmpRetString = undefined;") - returnExpr = "ret" - case .caseEnum(_): - bodyLines.append("const ret = \(call);") - returnExpr = "ret" - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - bodyLines.append("\(call);") - bodyLines.append("const ret = tmpRetString;") - bodyLines.append("tmpRetString = undefined;") - returnExpr = "ret" - case .bool: - bodyLines.append("const ret = \(call);") - returnExpr = "ret !== 0" - default: - bodyLines.append("const ret = \(call);") - returnExpr = "ret" - } - case .associatedValueEnum: - bodyLines.append("\(call);") - returnExpr = "\"\"" - case .namespaceEnum: - break - case .int, .float, .double: - bodyLines.append("const ret = \(call);") - returnExpr = "ret" - case .bool: - bodyLines.append("const ret = \(call) !== 0;") - returnExpr = "ret" - case .jsObject: - bodyLines.append("const retId = \(call);") - // TODO: Implement "take" operation - bodyLines.append("const ret = swift.memory.getObject(retId);") - bodyLines.append("swift.memory.release(retId);") - returnExpr = "ret" - case .swiftHeapObject(let name): - bodyLines.append("const ret = \(name).__construct(\(call));") - returnExpr = "ret" + let liftingFragment = try IntrinsicJSFragment.liftReturn(type: returnType) + assert( + liftingFragment.parameters.count <= 1, + "Lifting fragment should have at most one parameter to lift" + ) + let fragmentArguments: [String] + if liftingFragment.parameters.isEmpty { + body.write("\(call);") + fragmentArguments = [] + } else { + let returnVariable = scope.variable("ret") + body.write("const \(returnVariable) = \(call);") + fragmentArguments = [returnVariable] } - return returnExpr + let liftedValues = liftingFragment.printCode(fragmentArguments, scope, body, cleanupCode) + assert(liftedValues.count <= 1, "Lifting fragment should produce at most one value") + return liftedValues.first } func callConstructor(abiName: String) -> String { - let call = "instance.exports.\(abiName)(\(parameterForwardings.joined(separator: ", ")))" - bodyLines.append("const ret = \(call);") + let call = + "\(JSGlueVariableScope.reservedInstance).exports.\(abiName)(\(parameterForwardings.joined(separator: ", ")))" + body.write("const ret = \(call);") return "ret" } @@ -510,12 +454,13 @@ struct BridgeJSLink { guard effects.isThrows else { return [] } + let exceptionVariable = JSGlueVariableScope.reservedStorageToReturnException return [ - "if (tmpRetException) {", + "if (\(exceptionVariable)) {", // TODO: Implement "take" operation - " const error = swift.memory.getObject(tmpRetException);", - " swift.memory.release(tmpRetException);", - " tmpRetException = undefined;", + " const error = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(exceptionVariable));", + " \(JSGlueVariableScope.reservedSwift).memory.release(\(exceptionVariable));", + " \(exceptionVariable) = undefined;", " throw error;", "}", ] @@ -531,8 +476,8 @@ struct BridgeJSLink { funcLines.append( "\(declarationPrefixKeyword.map { "\($0) "} ?? "")\(name)(\(parameters.map { $0.name }.joined(separator: ", "))) {" ) - funcLines.append(contentsOf: bodyLines.map { $0.indent(count: 4) }) - funcLines.append(contentsOf: cleanupLines.map { $0.indent(count: 4) }) + funcLines.append(contentsOf: body.lines.map { $0.indent(count: 4) }) + funcLines.append(contentsOf: cleanupCode.lines.map { $0.indent(count: 4) }) funcLines.append(contentsOf: checkExceptionLines().map { $0.indent(count: 4) }) if let returnExpr = returnExpr { funcLines.append("return \(returnExpr);".indent(count: 4)) @@ -678,12 +623,12 @@ struct BridgeJSLink { return (jsLines, dtsLines) } - func renderExportedFunction(function: ExportedFunction) -> (js: [String], dts: [String]) { + func renderExportedFunction(function: ExportedFunction) throws -> (js: [String], dts: [String]) { let thunkBuilder = ExportedThunkBuilder(effects: function.effects) for param in function.parameters { - thunkBuilder.lowerParameter(param: param) + try thunkBuilder.lowerParameter(param: param) } - let returnExpr = thunkBuilder.call(abiName: function.abiName, returnType: function.returnType) + let returnExpr = try thunkBuilder.call(abiName: function.abiName, returnType: function.returnType) let funcLines = thunkBuilder.renderFunction( name: function.abiName, parameters: function.parameters, @@ -698,7 +643,9 @@ struct BridgeJSLink { return (funcLines, dtsLines) } - func renderExportedClass(_ klass: ExportedClass) -> (js: [String], dtsType: [String], dtsExportEntry: [String]) { + func renderExportedClass( + _ klass: ExportedClass + ) throws -> (js: [String], dtsType: [String], dtsExportEntry: [String]) { var jsLines: [String] = [] var dtsTypeLines: [String] = [] var dtsExportEntryLines: [String] = [] @@ -721,14 +668,14 @@ struct BridgeJSLink { if let constructor: ExportedConstructor = klass.constructor { let thunkBuilder = ExportedThunkBuilder(effects: constructor.effects) for param in constructor.parameters { - thunkBuilder.lowerParameter(param: param) + try thunkBuilder.lowerParameter(param: param) } var funcLines: [String] = [] funcLines.append("") funcLines.append("constructor(\(constructor.parameters.map { $0.name }.joined(separator: ", "))) {") let returnExpr = thunkBuilder.callConstructor(abiName: constructor.abiName) - funcLines.append(contentsOf: thunkBuilder.bodyLines.map { $0.indent(count: 4) }) - funcLines.append(contentsOf: thunkBuilder.cleanupLines.map { $0.indent(count: 4) }) + funcLines.append(contentsOf: thunkBuilder.body.lines.map { $0.indent(count: 4) }) + funcLines.append(contentsOf: thunkBuilder.cleanupCode.lines.map { $0.indent(count: 4) }) funcLines.append(contentsOf: thunkBuilder.checkExceptionLines().map { $0.indent(count: 4) }) funcLines.append("return \(klass.name).__construct(\(returnExpr));".indent(count: 4)) funcLines.append("}") @@ -744,9 +691,9 @@ struct BridgeJSLink { let thunkBuilder = ExportedThunkBuilder(effects: method.effects) thunkBuilder.lowerSelf() for param in method.parameters { - thunkBuilder.lowerParameter(param: param) + try thunkBuilder.lowerParameter(param: param) } - let returnExpr = thunkBuilder.call(abiName: method.abiName, returnType: method.returnType) + let returnExpr = try thunkBuilder.call(abiName: method.abiName, returnType: method.returnType) jsLines.append( contentsOf: thunkBuilder.renderFunction( name: method.name, @@ -766,7 +713,7 @@ struct BridgeJSLink { // Generate getter let getterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false)) getterThunkBuilder.lowerSelf() - let getterReturnExpr = getterThunkBuilder.call( + let getterReturnExpr = try getterThunkBuilder.call( abiName: property.getterAbiName(className: klass.name), returnType: property.type ) @@ -783,8 +730,10 @@ struct BridgeJSLink { if !property.isReadonly { let setterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false)) setterThunkBuilder.lowerSelf() - setterThunkBuilder.lowerParameter(param: Parameter(label: "value", name: "value", type: property.type)) - _ = setterThunkBuilder.call( + try setterThunkBuilder.lowerParameter( + param: Parameter(label: "value", name: "value", type: property.type) + ) + _ = try setterThunkBuilder.call( abiName: property.setterAbiName(className: klass.name), returnType: .void ) @@ -877,46 +826,38 @@ struct BridgeJSLink { } class ImportedThunkBuilder { - var bodyLines: [String] = [] + let body: CodeFragmentPrinter + let scope: JSGlueVariableScope + let cleanupCode: CodeFragmentPrinter var parameterNames: [String] = [] var parameterForwardings: [String] = [] + init() { + self.body = CodeFragmentPrinter() + self.scope = JSGlueVariableScope() + self.cleanupCode = CodeFragmentPrinter() + } + func liftSelf() { parameterNames.append("self") } - func liftParameter(param: Parameter) { - parameterNames.append(param.name) - switch param.type { - case .string: - let stringObjectName = "\(param.name)Object" - // TODO: Implement "take" operation - bodyLines.append("const \(stringObjectName) = swift.memory.getObject(\(param.name));") - bodyLines.append("swift.memory.release(\(param.name));") - parameterForwardings.append(stringObjectName) - case .caseEnum(_): - parameterForwardings.append(param.name) - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - let stringObjectName = "\(param.name)Object" - bodyLines.append("const \(stringObjectName) = swift.memory.getObject(\(param.name));") - bodyLines.append("swift.memory.release(\(param.name));") - parameterForwardings.append(stringObjectName) - case .bool: - parameterForwardings.append("\(param.name) !== 0") - default: - parameterForwardings.append(param.name) - } - case .associatedValueEnum: - parameterForwardings.append("\"\"") - case .namespaceEnum: - break - case .jsObject: - parameterForwardings.append("swift.memory.getObject(\(param.name))") - default: - parameterForwardings.append(param.name) + func liftParameter(param: Parameter) throws { + let liftingFragment = try IntrinsicJSFragment.liftParameter(type: param.type) + assert( + liftingFragment.parameters.count >= 1, + "Lifting fragment should have at least one parameter to lift" + ) + let valuesToLift: [String] + if liftingFragment.parameters.count == 1 { + parameterNames.append(param.name) + valuesToLift = [scope.variable(param.name)] + } else { + valuesToLift = liftingFragment.parameters.map { scope.variable(param.name + $0.capitalizedFirstLetter) } } + let liftedValues = liftingFragment.printCode(valuesToLift, scope, body, cleanupCode) + assert(liftedValues.count == 1, "Lifting fragment should produce exactly one value") + parameterForwardings.append(contentsOf: liftedValues) } func renderFunction( @@ -929,7 +870,7 @@ struct BridgeJSLink { "function \(name)(\(parameterNames.joined(separator: ", "))) {" ) funcLines.append("try {".indent(count: 4)) - funcLines.append(contentsOf: bodyLines.map { $0.indent(count: 8) }) + funcLines.append(contentsOf: body.lines.map { $0.indent(count: 8) }) if let returnExpr = returnExpr { funcLines.append("return \(returnExpr);".indent(count: 8)) } @@ -943,71 +884,69 @@ struct BridgeJSLink { return funcLines } - func call(name: String, returnType: BridgeType) { - let call = "imports.\(name)(\(parameterForwardings.joined(separator: ", ")))" - if returnType == .void { - bodyLines.append("\(call);") + func call(name: String, returnType: BridgeType) throws -> String? { + return try self.call(calleeExpr: "imports.\(name)", returnType: returnType) + } + + private func call(calleeExpr: String, returnType: BridgeType) throws -> String? { + let callExpr = "\(calleeExpr)(\(parameterForwardings.joined(separator: ", ")))" + return try self.call(callExpr: callExpr, returnType: returnType) + } + + private func call(callExpr: String, returnType: BridgeType) throws -> String? { + let loweringFragment = try IntrinsicJSFragment.lowerReturn(type: returnType) + let returnExpr: String? + if loweringFragment.parameters.count == 0 { + body.write("\(callExpr);") + returnExpr = nil } else { - bodyLines.append("let ret = \(call);") + let resultVariable = scope.variable("ret") + body.write("let \(resultVariable) = \(callExpr);") + returnExpr = resultVariable } + return try lowerReturnValue( + returnType: returnType, + returnExpr: returnExpr, + loweringFragment: loweringFragment + ) } - func callConstructor(name: String) { + func callConstructor(name: String) throws -> String? { let call = "new imports.\(name)(\(parameterForwardings.joined(separator: ", ")))" - bodyLines.append("let ret = \(call);") + let type: BridgeType = .jsObject(name) + let loweringFragment = try IntrinsicJSFragment.lowerReturn(type: type) + return try lowerReturnValue(returnType: type, returnExpr: call, loweringFragment: loweringFragment) } - func callMethod(name: String, returnType: BridgeType) { - let call = "swift.memory.getObject(self).\(name)(\(parameterForwardings.joined(separator: ", ")))" - if returnType == .void { - bodyLines.append("\(call);") - } else { - bodyLines.append("let ret = \(call);") - } + func callMethod(name: String, returnType: BridgeType) throws -> String? { + return try call( + calleeExpr: "\(JSGlueVariableScope.reservedSwift).memory.getObject(self).\(name)", + returnType: returnType + ) } - func callPropertyGetter(name: String, returnType: BridgeType) { - let call = "swift.memory.getObject(self).\(name)" - bodyLines.append("let ret = \(call);") + func callPropertyGetter(name: String, returnType: BridgeType) throws -> String? { + return try call( + callExpr: "\(JSGlueVariableScope.reservedSwift).memory.getObject(self).\(name)", + returnType: returnType + ) } func callPropertySetter(name: String, returnType: BridgeType) { - let call = "swift.memory.getObject(self).\(name) = \(parameterForwardings.joined(separator: ", "))" - bodyLines.append("\(call);") + let call = + "\(JSGlueVariableScope.reservedSwift).memory.getObject(self).\(name) = \(parameterForwardings.joined(separator: ", "))" + body.write("\(call);") } - func lowerReturnValue(returnType: BridgeType) throws -> String? { - switch returnType { - case .void: - return nil - case .string: - bodyLines.append("tmpRetBytes = textEncoder.encode(ret);") - return "tmpRetBytes.length" - case .caseEnum(_): - return "ret" - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - bodyLines.append("tmpRetBytes = textEncoder.encode(ret);") - return "tmpRetBytes.length" - case .bool: - return "ret ? 1 : 0" - default: - return "ret" - } - case .associatedValueEnum: - return nil - case .namespaceEnum: - return nil - case .int, .float, .double: - return "ret" - case .bool: - return "ret !== 0" - case .jsObject: - return "swift.memory.retain(ret)" - case .swiftHeapObject: - throw BridgeJSLinkError(message: "Swift heap object is not supported in imported functions") - } + private func lowerReturnValue( + returnType: BridgeType, + returnExpr: String?, + loweringFragment: IntrinsicJSFragment + ) throws -> String? { + assert(loweringFragment.parameters.count <= 1, "Lowering fragment should have at most one parameter") + let loweredValues = loweringFragment.printCode(returnExpr.map { [$0] } ?? [], scope, body, cleanupCode) + assert(loweredValues.count <= 1, "Lowering fragment should produce at most one value") + return loweredValues.first } } @@ -1385,10 +1324,9 @@ struct BridgeJSLink { ) throws { let thunkBuilder = ImportedThunkBuilder() for param in function.parameters { - thunkBuilder.liftParameter(param: param) + try thunkBuilder.liftParameter(param: param) } - thunkBuilder.call(name: function.name, returnType: function.returnType) - let returnExpr = try thunkBuilder.lowerReturnValue(returnType: function.returnType) + let returnExpr = try thunkBuilder.call(name: function.name, returnType: function.returnType) let funcLines = thunkBuilder.renderFunction( name: function.abiName(context: nil), returnExpr: returnExpr, @@ -1420,8 +1358,7 @@ struct BridgeJSLink { property: property, abiName: getterAbiName, emitCall: { thunkBuilder in - thunkBuilder.callPropertyGetter(name: property.name, returnType: property.type) - return try thunkBuilder.lowerReturnValue(returnType: property.type) + return try thunkBuilder.callPropertyGetter(name: property.name, returnType: property.type) } ) importObjectBuilder.assignToImportObject(name: getterAbiName, function: js) @@ -1433,7 +1370,7 @@ struct BridgeJSLink { property: property, abiName: setterAbiName, emitCall: { thunkBuilder in - thunkBuilder.liftParameter( + try thunkBuilder.liftParameter( param: Parameter(label: nil, name: "newValue", type: property.type) ) thunkBuilder.callPropertySetter(name: property.name, returnType: property.type) @@ -1458,11 +1395,10 @@ struct BridgeJSLink { ) throws { let thunkBuilder = ImportedThunkBuilder() for param in constructor.parameters { - thunkBuilder.liftParameter(param: param) + try thunkBuilder.liftParameter(param: param) } let returnType = BridgeType.jsObject(type.name) - thunkBuilder.callConstructor(name: type.name) - let returnExpr = try thunkBuilder.lowerReturnValue(returnType: returnType) + let returnExpr = try thunkBuilder.callConstructor(name: type.name) let abiName = constructor.abiName(context: type) let funcLines = thunkBuilder.renderFunction( name: abiName, @@ -1501,10 +1437,9 @@ struct BridgeJSLink { let thunkBuilder = ImportedThunkBuilder() thunkBuilder.liftSelf() for param in method.parameters { - thunkBuilder.liftParameter(param: param) + try thunkBuilder.liftParameter(param: param) } - thunkBuilder.callMethod(name: method.name, returnType: method.returnType) - let returnExpr = try thunkBuilder.lowerReturnValue(returnType: method.returnType) + let returnExpr = try thunkBuilder.callMethod(name: method.name, returnType: method.returnType) let funcLines = thunkBuilder.renderFunction( name: method.abiName(context: context), returnExpr: returnExpr, @@ -1524,13 +1459,6 @@ extension String { } } -fileprivate extension String { - var capitalizedFirstLetter: String { - guard !isEmpty else { return self } - return prefix(1).uppercased() + dropFirst() - } -} - extension BridgeType { var tsType: String { switch self { diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/CodeFragmentPrinter.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/CodeFragmentPrinter.swift new file mode 100644 index 00000000..c4624e69 --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/CodeFragmentPrinter.swift @@ -0,0 +1,41 @@ +/// A printer for code fragments. +final class CodeFragmentPrinter { + private(set) var lines: [String] = [] + private var indentLevel: Int = 0 + + init(header: String = "") { + self.lines.append(contentsOf: header.split(separator: "\n").map { String($0) }) + } + + func nextLine() { + lines.append("") + } + + func write(_ line: S) { + lines.append(String(repeating: " ", count: indentLevel * 4) + String(line)) + } + + func write(lines: [String]) { + for line in lines { + write(line) + } + } + + func write(contentsOf printer: CodeFragmentPrinter) { + self.write(lines: printer.lines) + } + + func indent() { + indentLevel += 1 + } + + func unindent() { + indentLevel -= 1 + } + + func indent(_ body: () throws -> Void) rethrows { + indentLevel += 1 + try body() + indentLevel -= 1 + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift new file mode 100644 index 00000000..ae74844f --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -0,0 +1,317 @@ +#if canImport(BridgeJSSkeleton) +import BridgeJSSkeleton +#endif + +/// A scope for variables for JS glue code +final class JSGlueVariableScope { + // MARK: - Reserved variables + + static let reservedSwift = "swift" + static let reservedInstance = "instance" + static let reservedMemory = "memory" + static let reservedSetException = "setException" + static let reservedStorageToReturnString = "tmpRetString" + static let reservedStorageToReturnBytes = "tmpRetBytes" + static let reservedStorageToReturnException = "tmpRetException" + static let reservedTextEncoder = "textEncoder" + static let reservedTextDecoder = "textDecoder" + + private var variables: Set = [ + reservedSwift, + reservedMemory, + reservedStorageToReturnString, + reservedStorageToReturnBytes, + reservedStorageToReturnException, + reservedTextEncoder, + reservedTextDecoder, + ] + + /// Returns a unique variable name in the scope based on the given name hint. + /// + /// - Parameter hint: A hint for the variable name. + /// - Returns: A unique variable name. + func variable(_ hint: String) -> String { + if variables.insert(hint).inserted { + return hint + } + var suffixedName: String + var suffix = 1 + repeat { + suffixedName = hint + suffix.description + suffix += 1 + } while !variables.insert(suffixedName).inserted + return suffixedName + } +} + +/// A fragment of JS code used to convert a value between Swift and JS. +/// +/// See `BridgeJSInstrincics.swift` in the main JavaScriptKit module for Swift side lowering/lifting implementation. +struct IntrinsicJSFragment: Sendable { + /// The names of the parameters that the fragment expects. + let parameters: [String] + + /// Prints the fragment code. + /// + /// - Parameters: + /// - arguments: The arguments that the fragment expects. An argument may be an expression with side effects, + /// so the callee is responsible for evaluating the arguments only once. + /// - scope: The scope of the variables. + /// - printer: The printer to print the main fragment code. + /// - cleanupCode: The printer to print the code that is expected to be executed at the end of the caller of the + /// fragment. + /// - Returns: List of result expressions. + let printCode: + @Sendable ( + _ arguments: [String], + _ scope: JSGlueVariableScope, + _ printer: CodeFragmentPrinter, + _ cleanupCode: CodeFragmentPrinter + ) -> [String] + + /// A fragment that does nothing + static let void = IntrinsicJSFragment( + parameters: [], + printCode: { _, _, _, _ in + return [] + } + ) + + /// A fragment that returns the argument as is. + static let identity = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanupCode in + return [arguments[0]] + } + ) + + /// 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, scope, printer, cleanupCode in + return ["\(arguments[0]) !== 0"] + } + ) + static let boolLiftParameter = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanupCode in + return ["\(arguments[0]) !== 0"] + } + ) + static let boolLowerReturn = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanupCode in + return ["\(arguments[0]) ? 1 : 0"] + } + ) + + static let stringLowerParameter = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanupCode in + let argument = arguments[0] + let bytesLabel = scope.variable("\(argument)Bytes") + let bytesIdLabel = scope.variable("\(argument)Id") + printer.write("const \(bytesLabel) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(argument));") + printer.write("const \(bytesIdLabel) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesLabel));") + cleanupCode.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(bytesIdLabel));") + return [bytesIdLabel, "\(bytesLabel).length"] + } + ) + static let stringLiftReturn = IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanupCode in + let resultLabel = scope.variable("ret") + printer.write("const \(resultLabel) = \(JSGlueVariableScope.reservedStorageToReturnString);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") + return [resultLabel] + } + ) + static let stringLiftParameter = IntrinsicJSFragment( + parameters: ["objectId"], + printCode: { arguments, scope, printer, cleanupCode in + 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("\(JSGlueVariableScope.reservedSwift).memory.release(\(objectId));") + return [objectLabel] + } + ) + static let stringLowerReturn = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanupCode in + printer.write( + "\(JSGlueVariableScope.reservedStorageToReturnBytes) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(arguments[0]));" + ) + return ["\(JSGlueVariableScope.reservedStorageToReturnBytes).length"] + } + ) + + static let jsObjectLowerParameter = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanupCode in + return ["swift.memory.retain(\(arguments[0]))"] + } + ) + static let jsObjectLiftReturn = IntrinsicJSFragment( + parameters: ["retId"], + printCode: { arguments, scope, printer, cleanupCode in + // 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 jsObjectLiftParameter = IntrinsicJSFragment( + parameters: ["objectId"], + printCode: { arguments, scope, printer, cleanupCode in + return ["\(JSGlueVariableScope.reservedSwift).memory.getObject(\(arguments[0]))"] + } + ) + static let jsObjectLowerReturn = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanupCode in + return ["\(JSGlueVariableScope.reservedSwift).memory.retain(\(arguments[0]))"] + } + ) + + static let swiftHeapObjectLowerParameter = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanupCode in + return ["\(arguments[0]).pointer"] + } + ) + static func swiftHeapObjectLiftReturn(_ name: String) -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanupCode in + return ["\(name).__construct(\(arguments[0]))"] + } + ) + } + + // MARK: - ExportSwift + + /// Returns a fragment that lowers a JS value to Wasm core values for parameters + static func lowerParameter(type: BridgeType) throws -> IntrinsicJSFragment { + switch type { + case .int, .float, .double, .bool: return .identity + case .string: return .stringLowerParameter + case .jsObject: return .jsObjectLowerParameter + case .swiftHeapObject: + return .swiftHeapObjectLowerParameter + case .void: return .void + case .caseEnum: return .identity + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: return .stringLowerParameter + default: return .identity + } + case .associatedValueEnum(let string): + throw BridgeJSLinkError( + message: "Associated value enums are not supported to be passed as parameters: \(string)" + ) + case .namespaceEnum(let string): + throw BridgeJSLinkError(message: "Namespace enums are not supported to be passed as parameters: \(string)") + } + } + + /// Returns a fragment that lifts a Wasm core value to a JS value for return values + static func liftReturn(type: BridgeType) throws -> IntrinsicJSFragment { + switch type { + case .int, .float, .double: return .identity + case .bool: return .boolLiftReturn + case .string: return .stringLiftReturn + case .jsObject: return .jsObjectLiftReturn + case .swiftHeapObject(let name): return .swiftHeapObjectLiftReturn(name) + case .void: return .void + case .caseEnum: return .identity + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: return .stringLiftReturn + case .bool: return .boolLiftReturn + default: return .identity + } + case .associatedValueEnum(let string): + throw BridgeJSLinkError( + message: "Associated value enums are not supported to be returned from functions: \(string)" + ) + case .namespaceEnum(let string): + throw BridgeJSLinkError( + message: "Namespace enums are not supported to be returned from functions: \(string)" + ) + } + } + + // MARK: - ImportedJS + + /// Returns a fragment that lifts Wasm core values to JS values for parameters + static func liftParameter(type: BridgeType) throws -> IntrinsicJSFragment { + switch type { + case .int, .float, .double: return .identity + case .bool: return .boolLiftParameter + case .string: return .stringLiftParameter + case .jsObject: return .jsObjectLiftParameter + case .swiftHeapObject(let name): + throw BridgeJSLinkError( + message: + "Swift heap objects are not supported to be passed as parameters to imported JS functions: \(name)" + ) + case .void: + throw BridgeJSLinkError( + message: "Void can't appear in parameters of imported JS functions" + ) + case .caseEnum: return .identity + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: return .stringLiftParameter + case .bool: return .boolLiftParameter + default: return .identity + } + case .associatedValueEnum(let string): + throw BridgeJSLinkError( + message: + "Associated value enums are not supported to be passed as parameters to imported JS functions: \(string)" + ) + case .namespaceEnum(let string): + throw BridgeJSLinkError( + message: + "Namespace enums are not supported to be passed as parameters to imported JS functions: \(string)" + ) + } + } + + /// Returns a fragment that lowers a JS value to Wasm core values for return values + static func lowerReturn(type: BridgeType) throws -> IntrinsicJSFragment { + switch type { + case .int, .float, .double: return .identity + case .bool: return .boolLowerReturn + case .string: return .stringLowerReturn + case .jsObject: return .jsObjectLowerReturn + case .swiftHeapObject: + throw BridgeJSLinkError( + message: "Swift heap objects are not supported to be returned from imported JS functions" + ) + case .void: return .void + case .caseEnum: return .identity + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: return .stringLowerReturn + case .bool: return .boolLowerReturn + default: return .identity + } + case .associatedValueEnum(let string): + throw BridgeJSLinkError( + message: "Associated value enums are not supported to be returned from imported JS functions: \(string)" + ) + case .namespaceEnum(let string): + throw BridgeJSLinkError( + message: "Namespace enums are not supported to be returned from imported JS functions: \(string)" + ) + } + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift index 47083729..76385d41 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift @@ -10,7 +10,7 @@ public enum BridgeType: Codable, Equatable { case namespaceEnum(String) } -public enum WasmCoreType: String, Codable { +public enum WasmCoreType: String, Codable, Sendable { case i32, i64, f32, f64, pointer } diff --git a/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift b/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift new file mode 100644 index 00000000..f091e4a3 --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift @@ -0,0 +1,6 @@ +extension String { + public var capitalizedFirstLetter: String { + guard !isEmpty else { return self } + return prefix(1).uppercased() + dropFirst() + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js index 1da2f58e..97c1e215 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js @@ -65,49 +65,49 @@ export async function createInstantiator(options, swift) { return { asyncReturnVoid: function bjs_asyncReturnVoid() { - const retId = instance.exports.bjs_asyncReturnVoid(); - const ret = swift.memory.getObject(retId); - swift.memory.release(retId); - return ret; + const ret = instance.exports.bjs_asyncReturnVoid(); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; }, asyncRoundTripInt: function bjs_asyncRoundTripInt(v) { - const retId = instance.exports.bjs_asyncRoundTripInt(v); - const ret = swift.memory.getObject(retId); - swift.memory.release(retId); - return ret; + const ret = instance.exports.bjs_asyncRoundTripInt(v); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; }, asyncRoundTripString: function bjs_asyncRoundTripString(v) { const vBytes = textEncoder.encode(v); const vId = swift.memory.retain(vBytes); - const retId = instance.exports.bjs_asyncRoundTripString(vId, vBytes.length); - const ret = swift.memory.getObject(retId); - swift.memory.release(retId); + const ret = instance.exports.bjs_asyncRoundTripString(vId, vBytes.length); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); swift.memory.release(vId); - return ret; + return ret1; }, asyncRoundTripBool: function bjs_asyncRoundTripBool(v) { - const retId = instance.exports.bjs_asyncRoundTripBool(v); - const ret = swift.memory.getObject(retId); - swift.memory.release(retId); - return ret; + const ret = instance.exports.bjs_asyncRoundTripBool(v); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; }, asyncRoundTripFloat: function bjs_asyncRoundTripFloat(v) { - const retId = instance.exports.bjs_asyncRoundTripFloat(v); - const ret = swift.memory.getObject(retId); - swift.memory.release(retId); - return ret; + const ret = instance.exports.bjs_asyncRoundTripFloat(v); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; }, asyncRoundTripDouble: function bjs_asyncRoundTripDouble(v) { - const retId = instance.exports.bjs_asyncRoundTripDouble(v); - const ret = swift.memory.getObject(retId); - swift.memory.release(retId); - return ret; + const ret = instance.exports.bjs_asyncRoundTripDouble(v); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; }, asyncRoundTripJSObject: function bjs_asyncRoundTripJSObject(v) { - const retId = instance.exports.bjs_asyncRoundTripJSObject(swift.memory.retain(v)); - const ret = swift.memory.getObject(retId); - swift.memory.release(retId); - return ret; + const ret = instance.exports.bjs_asyncRoundTripJSObject(swift.memory.retain(v)); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; }, }; }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js index 21d11fa4..0b07aedd 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js @@ -82,7 +82,7 @@ export async function createInstantiator(options, swift) { } TestModule["bjs_asyncRoundTripBool"] = function bjs_asyncRoundTripBool(v) { try { - let ret = imports.asyncRoundTripBool(v); + let ret = imports.asyncRoundTripBool(v !== 0); return swift.memory.retain(ret); } catch (error) { setException(error); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js index 3e080948..42a98f62 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js @@ -86,18 +86,18 @@ export async function createInstantiator(options, swift) { return { setDirection: function bjs_setDirection(direction) { - instance.exports.bjs_setDirection(direction | 0); + instance.exports.bjs_setDirection(direction); }, getDirection: function bjs_getDirection() { const ret = instance.exports.bjs_getDirection(); return ret; }, processDirection: function bjs_processDirection(input) { - const ret = instance.exports.bjs_processDirection(input | 0); + const ret = instance.exports.bjs_processDirection(input); return ret; }, setTSDirection: function bjs_setTSDirection(direction) { - instance.exports.bjs_setTSDirection(direction | 0); + instance.exports.bjs_setTSDirection(direction); }, getTSDirection: function bjs_getTSDirection() { const ret = instance.exports.bjs_getTSDirection(); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js index 12613dd8..677e02c9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js @@ -171,7 +171,7 @@ export async function createInstantiator(options, swift) { return HTTPServer.__construct(ret); } call(method) { - instance.exports.bjs_HTTPServer_call(this.pointer, method | 0); + instance.exports.bjs_HTTPServer_call(this.pointer, method); } } class TestServer extends SwiftHeapObject { @@ -185,7 +185,7 @@ export async function createInstantiator(options, swift) { return TestServer.__construct(ret); } call(method) { - instance.exports.bjs_TestServer_call(this.pointer, method | 0); + instance.exports.bjs_TestServer_call(this.pointer, method); } } const exports = { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js index 68a2b19f..2be034b4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js @@ -165,7 +165,7 @@ export async function createInstantiator(options, swift) { return ret; }, setFeatureFlag: function bjs_setFeatureFlag(flag) { - instance.exports.bjs_setFeatureFlag(flag ? 1 : 0); + instance.exports.bjs_setFeatureFlag(flag); }, getFeatureFlag: function bjs_getFeatureFlag() { const ret = instance.exports.bjs_getFeatureFlag(); @@ -235,7 +235,7 @@ export async function createInstantiator(options, swift) { return ret; }, setFeatureFlag: function bjs_setFeatureFlag(featureFlag) { - instance.exports.bjs_setFeatureFlag(featureFlag ? 1 : 0); + instance.exports.bjs_setFeatureFlag(featureFlag); }, getFeatureFlag: function bjs_getFeatureFlag() { const ret = instance.exports.bjs_getFeatureFlag(); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js index 394d996b..d9a13b5e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js @@ -83,7 +83,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_DatabaseConnection_isConnected_get"] = function bjs_DatabaseConnection_isConnected_get(self) { try { let ret = swift.memory.getObject(self).isConnected; - return ret !== 0; + return ret ? 1 : 0; } catch (error) { setException(error); return 0 diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js index 3b93b2dd..b0dbaa19 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js @@ -53,7 +53,7 @@ export async function createInstantiator(options, swift) { const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_check"] = function bjs_check(a, b) { try { - imports.check(a, b); + imports.check(a, b !== 0); } catch (error) { setException(error); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js index 53332b97..594dc9d5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js @@ -77,8 +77,8 @@ export async function createInstantiator(options, swift) { return ret; }, checkBool: function bjs_checkBool() { - const ret = instance.exports.bjs_checkBool() !== 0; - return ret; + const ret = instance.exports.bjs_checkBool(); + return ret !== 0; }, }; }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js index 1892eb46..a61149cd 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js @@ -63,7 +63,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_checkBoolean"] = function bjs_checkBoolean() { try { let ret = imports.checkBoolean(); - return ret !== 0; + return ret ? 1 : 0; } catch (error) { setException(error); return 0 diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.Export.js index ae72be66..ffc1eab6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.Export.js @@ -129,8 +129,8 @@ export async function createInstantiator(options, swift) { instance.exports.bjs_PropertyHolder_doubleValue_set(this.pointer, value); } get boolValue() { - const ret = instance.exports.bjs_PropertyHolder_boolValue_get(this.pointer) !== 0; - return ret; + const ret = instance.exports.bjs_PropertyHolder_boolValue_get(this.pointer); + return ret !== 0; } set boolValue(value) { instance.exports.bjs_PropertyHolder_boolValue_set(this.pointer, value); @@ -160,8 +160,8 @@ export async function createInstantiator(options, swift) { return ret; } get readonlyBool() { - const ret = instance.exports.bjs_PropertyHolder_readonlyBool_get(this.pointer) !== 0; - return ret; + const ret = instance.exports.bjs_PropertyHolder_readonlyBool_get(this.pointer); + return ret !== 0; } get readonlyString() { instance.exports.bjs_PropertyHolder_readonlyString_get(this.pointer); @@ -170,17 +170,17 @@ export async function createInstantiator(options, swift) { return ret; } get jsObject() { - const retId = instance.exports.bjs_PropertyHolder_jsObject_get(this.pointer); - const ret = swift.memory.getObject(retId); - swift.memory.release(retId); - return ret; + const ret = instance.exports.bjs_PropertyHolder_jsObject_get(this.pointer); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; } set jsObject(value) { instance.exports.bjs_PropertyHolder_jsObject_set(this.pointer, swift.memory.retain(value)); } get sibling() { - const ret = PropertyHolder.__construct(instance.exports.bjs_PropertyHolder_sibling_get(this.pointer)); - return ret; + const ret = instance.exports.bjs_PropertyHolder_sibling_get(this.pointer); + return PropertyHolder.__construct(ret); } set sibling(value) { instance.exports.bjs_PropertyHolder_sibling_set(this.pointer, value.pointer); @@ -226,9 +226,9 @@ export async function createInstantiator(options, swift) { createPropertyHolder: function bjs_createPropertyHolder(intValue, floatValue, doubleValue, boolValue, stringValue, jsObject) { const stringValueBytes = textEncoder.encode(stringValue); const stringValueId = swift.memory.retain(stringValueBytes); - const ret = PropertyHolder.__construct(instance.exports.bjs_createPropertyHolder(intValue, floatValue, doubleValue, boolValue, stringValueId, stringValueBytes.length, swift.memory.retain(jsObject))); + const ret = instance.exports.bjs_createPropertyHolder(intValue, floatValue, doubleValue, boolValue, stringValueId, stringValueBytes.length, swift.memory.retain(jsObject)); swift.memory.release(stringValueId); - return ret; + return PropertyHolder.__construct(ret); }, testPropertyHolder: function bjs_testPropertyHolder(holder) { instance.exports.bjs_testPropertyHolder(holder.pointer); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js index 705c6a37..c7671805 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js @@ -96,7 +96,7 @@ export async function createInstantiator(options, swift) { const tsObject = swift.memory.getObject(ts); swift.memory.release(ts); let ret = swift.memory.getObject(self).validate(tsObject); - return ret !== 0; + return ret ? 1 : 0; } catch (error) { setException(error); return 0 diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js index c7d622ea..48d15c7e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js @@ -55,8 +55,7 @@ export async function createInstantiator(options, swift) { try { const nameObject = swift.memory.getObject(name); swift.memory.release(name); - let ret = new imports.Greeter(nameObject); - return swift.memory.retain(ret); + return swift.memory.retain(new imports.Greeter(nameObject)); } catch (error) { setException(error); return 0 diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Async.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Async.swift index 10a3a24d..33ddda25 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Async.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Async.swift @@ -13,7 +13,7 @@ public func _bjs_asyncReturnVoid() -> Int32 { let ret = JSPromise.async { await asyncReturnVoid() } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -24,9 +24,9 @@ public func _bjs_asyncReturnVoid() -> Int32 { public func _bjs_asyncRoundTripInt(v: Int32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { - return await asyncRoundTripInt(_: Int(v)).jsValue + return await asyncRoundTripInt(_: Int.bridgeJSLiftParameter(v)).jsValue } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -34,16 +34,12 @@ public func _bjs_asyncRoundTripInt(v: Int32) -> Int32 { @_expose(wasm, "bjs_asyncRoundTripString") @_cdecl("bjs_asyncRoundTripString") -public func _bjs_asyncRoundTripString(vBytes: Int32, vLen: Int32) -> Int32 { +public func _bjs_asyncRoundTripString(vBytes: Int32, vLength: Int32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { - let v = String(unsafeUninitializedCapacity: Int(vLen)) { b in - _swift_js_init_memory(vBytes, b.baseAddress.unsafelyUnwrapped) - return Int(vLen) - } - return await asyncRoundTripString(_: v).jsValue + return await asyncRoundTripString(_: String.bridgeJSLiftParameter(vBytes, vLength)).jsValue } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -54,9 +50,9 @@ public func _bjs_asyncRoundTripString(vBytes: Int32, vLen: Int32) -> Int32 { public func _bjs_asyncRoundTripBool(v: Int32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { - return await asyncRoundTripBool(_: v == 1).jsValue + return await asyncRoundTripBool(_: Bool.bridgeJSLiftParameter(v)).jsValue } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -67,9 +63,9 @@ public func _bjs_asyncRoundTripBool(v: Int32) -> Int32 { public func _bjs_asyncRoundTripFloat(v: Float32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { - return await asyncRoundTripFloat(_: v).jsValue + return await asyncRoundTripFloat(_: Float.bridgeJSLiftParameter(v)).jsValue } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -80,9 +76,9 @@ public func _bjs_asyncRoundTripFloat(v: Float32) -> Int32 { public func _bjs_asyncRoundTripDouble(v: Float64) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { - return await asyncRoundTripDouble(_: v).jsValue + return await asyncRoundTripDouble(_: Double.bridgeJSLiftParameter(v)).jsValue } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -93,9 +89,9 @@ public func _bjs_asyncRoundTripDouble(v: Float64) -> Int32 { public func _bjs_asyncRoundTripJSObject(v: Int32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { - return await asyncRoundTripJSObject(_: JSObject(id: UInt32(bitPattern: v))).jsValue + return await asyncRoundTripJSObject(_: JSObject.bridgeJSLiftParameter(v)).jsValue } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumCase.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumCase.swift index 363ade82..8b087111 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumCase.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumCase.swift @@ -7,7 +7,20 @@ @_spi(BridgeJS) import JavaScriptKit extension Direction { - init?(bridgeJSRawValue: Int32) { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Direction { + return Direction(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Direction { + return Direction(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSRawValue + } + + private init?(bridgeJSRawValue: Int32) { switch bridgeJSRawValue { case 0: self = .north @@ -22,7 +35,7 @@ extension Direction { } } - var bridgeJSRawValue: Int32 { + private var bridgeJSRawValue: Int32 { switch self { case .north: return 0 @@ -37,7 +50,20 @@ extension Direction { } extension Status { - init?(bridgeJSRawValue: Int32) { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Status { + return Status(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Status { + return Status(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSRawValue + } + + private init?(bridgeJSRawValue: Int32) { switch bridgeJSRawValue { case 0: self = .loading @@ -50,7 +76,7 @@ extension Status { } } - var bridgeJSRawValue: Int32 { + private var bridgeJSRawValue: Int32 { switch self { case .loading: return 0 @@ -63,7 +89,20 @@ extension Status { } extension TSDirection { - init?(bridgeJSRawValue: Int32) { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> TSDirection { + return TSDirection(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> TSDirection { + return TSDirection(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSRawValue + } + + private init?(bridgeJSRawValue: Int32) { switch bridgeJSRawValue { case 0: self = .north @@ -78,7 +117,7 @@ extension TSDirection { } } - var bridgeJSRawValue: Int32 { + private var bridgeJSRawValue: Int32 { switch self { case .north: return 0 @@ -96,7 +135,7 @@ extension TSDirection { @_cdecl("bjs_setDirection") public func _bjs_setDirection(direction: Int32) -> Void { #if arch(wasm32) - setDirection(_: Direction(bridgeJSRawValue: direction)!) + setDirection(_: Direction.bridgeJSLiftParameter(direction)) #else fatalError("Only available on WebAssembly") #endif @@ -107,7 +146,7 @@ public func _bjs_setDirection(direction: Int32) -> Void { public func _bjs_getDirection() -> Int32 { #if arch(wasm32) let ret = getDirection() - return ret.bridgeJSRawValue + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -117,8 +156,8 @@ public func _bjs_getDirection() -> Int32 { @_cdecl("bjs_processDirection") public func _bjs_processDirection(input: Int32) -> Int32 { #if arch(wasm32) - let ret = processDirection(_: Direction(bridgeJSRawValue: input)!) - return ret.bridgeJSRawValue + let ret = processDirection(_: Direction.bridgeJSLiftParameter(input)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -128,7 +167,7 @@ public func _bjs_processDirection(input: Int32) -> Int32 { @_cdecl("bjs_setTSDirection") public func _bjs_setTSDirection(direction: Int32) -> Void { #if arch(wasm32) - setTSDirection(_: TSDirection(bridgeJSRawValue: direction)!) + setTSDirection(_: TSDirection.bridgeJSLiftParameter(direction)) #else fatalError("Only available on WebAssembly") #endif @@ -139,7 +178,7 @@ public func _bjs_setTSDirection(direction: Int32) -> Void { public func _bjs_getTSDirection() -> Int32 { #if arch(wasm32) let ret = getTSDirection() - return ret.bridgeJSRawValue + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumNamespace.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumNamespace.swift index 9517ad80..bb0fbe43 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumNamespace.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumNamespace.swift @@ -6,8 +6,24 @@ @_spi(BridgeJS) import JavaScriptKit +extension Utils: _BridgedSwiftEnumNoPayload { +} + extension Networking.API.Method { - init?(bridgeJSRawValue: Int32) { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Networking.API.Method { + return Networking.API.Method(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Networking.API.Method { + return Networking.API.Method(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSRawValue + } + + private init?(bridgeJSRawValue: Int32) { switch bridgeJSRawValue { case 0: self = .get @@ -22,7 +38,7 @@ extension Networking.API.Method { } } - var bridgeJSRawValue: Int32 { + private var bridgeJSRawValue: Int32 { switch self { case .get: return 0 @@ -36,8 +52,27 @@ extension Networking.API.Method { } } +extension Configuration.LogLevel: _BridgedSwiftEnumNoPayload { +} + +extension Configuration.Port: _BridgedSwiftEnumNoPayload { +} + extension Internal.SupportedMethod { - init?(bridgeJSRawValue: Int32) { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Internal.SupportedMethod { + return Internal.SupportedMethod(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Internal.SupportedMethod { + return Internal.SupportedMethod(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSRawValue + } + + private init?(bridgeJSRawValue: Int32) { switch bridgeJSRawValue { case 0: self = .get @@ -48,7 +83,7 @@ extension Internal.SupportedMethod { } } - var bridgeJSRawValue: Int32 { + private var bridgeJSRawValue: Int32 { switch self { case .get: return 0 @@ -63,7 +98,7 @@ extension Internal.SupportedMethod { public func _bjs_Converter_init() -> UnsafeMutableRawPointer { #if arch(wasm32) let ret = Utils.Converter() - return Unmanaged.passRetained(ret).toOpaque() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -73,10 +108,8 @@ public func _bjs_Converter_init() -> UnsafeMutableRawPointer { @_cdecl("bjs_Converter_toString") public func _bjs_Converter_toString(_self: UnsafeMutableRawPointer, value: Int32) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().toString(value: Int(value)) - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = Utils.Converter.bridgeJSLiftParameter(_self).toString(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -88,10 +121,16 @@ public func _bjs_Converter_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension Utils.Converter: ConvertibleToJSValue { +extension Utils.Converter: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_Converter_wrap") func _bjs_Converter_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_Converter_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_Converter_wrap(Unmanaged.passRetained(self).toOpaque())))) } } @@ -101,7 +140,7 @@ extension Utils.Converter: ConvertibleToJSValue { public func _bjs_HTTPServer_init() -> UnsafeMutableRawPointer { #if arch(wasm32) let ret = Networking.API.HTTPServer() - return Unmanaged.passRetained(ret).toOpaque() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -111,7 +150,7 @@ public func _bjs_HTTPServer_init() -> UnsafeMutableRawPointer { @_cdecl("bjs_HTTPServer_call") public func _bjs_HTTPServer_call(_self: UnsafeMutableRawPointer, method: Int32) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().call(_: Networking.API.Method(bridgeJSRawValue: method)!) + Networking.API.HTTPServer.bridgeJSLiftParameter(_self).call(_: Networking.API.Method.bridgeJSLiftParameter(method)) #else fatalError("Only available on WebAssembly") #endif @@ -123,10 +162,16 @@ public func _bjs_HTTPServer_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension Networking.API.HTTPServer: ConvertibleToJSValue { +extension Networking.API.HTTPServer: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_HTTPServer_wrap") func _bjs_HTTPServer_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_HTTPServer_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_HTTPServer_wrap(Unmanaged.passRetained(self).toOpaque())))) } } @@ -136,7 +181,7 @@ extension Networking.API.HTTPServer: ConvertibleToJSValue { public func _bjs_TestServer_init() -> UnsafeMutableRawPointer { #if arch(wasm32) let ret = Internal.TestServer() - return Unmanaged.passRetained(ret).toOpaque() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -146,7 +191,7 @@ public func _bjs_TestServer_init() -> UnsafeMutableRawPointer { @_cdecl("bjs_TestServer_call") public func _bjs_TestServer_call(_self: UnsafeMutableRawPointer, method: Int32) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().call(_: Internal.SupportedMethod(bridgeJSRawValue: method)!) + Internal.TestServer.bridgeJSLiftParameter(_self).call(_: Internal.SupportedMethod.bridgeJSLiftParameter(method)) #else fatalError("Only available on WebAssembly") #endif @@ -158,10 +203,16 @@ public func _bjs_TestServer_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension Internal.TestServer: ConvertibleToJSValue { +extension Internal.TestServer: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_TestServer_wrap") func _bjs_TestServer_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_TestServer_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_TestServer_wrap(Unmanaged.passRetained(self).toOpaque())))) } } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.swift index 991b5c6c..e0a32e84 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.swift @@ -6,15 +6,47 @@ @_spi(BridgeJS) import JavaScriptKit +extension Theme: _BridgedSwiftEnumNoPayload { +} + +extension TSTheme: _BridgedSwiftEnumNoPayload { +} + +extension FeatureFlag: _BridgedSwiftEnumNoPayload { +} + +extension HttpStatus: _BridgedSwiftEnumNoPayload { +} + +extension TSHttpStatus: _BridgedSwiftEnumNoPayload { +} + +extension Priority: _BridgedSwiftEnumNoPayload { +} + +extension FileSize: _BridgedSwiftEnumNoPayload { +} + +extension UserId: _BridgedSwiftEnumNoPayload { +} + +extension TokenId: _BridgedSwiftEnumNoPayload { +} + +extension SessionId: _BridgedSwiftEnumNoPayload { +} + +extension Precision: _BridgedSwiftEnumNoPayload { +} + +extension Ratio: _BridgedSwiftEnumNoPayload { +} + @_expose(wasm, "bjs_setTheme") @_cdecl("bjs_setTheme") -public func _bjs_setTheme(themeBytes: Int32, themeLen: Int32) -> Void { +public func _bjs_setTheme(themeBytes: Int32, themeLength: Int32) -> Void { #if arch(wasm32) - let theme = String(unsafeUninitializedCapacity: Int(themeLen)) { b in - _swift_js_init_memory(themeBytes, b.baseAddress.unsafelyUnwrapped) - return Int(themeLen) - } - setTheme(_: Theme(rawValue: theme)!) + setTheme(_: Theme.bridgeJSLiftParameter(themeBytes, themeLength)) #else fatalError("Only available on WebAssembly") #endif @@ -25,10 +57,7 @@ public func _bjs_setTheme(themeBytes: Int32, themeLen: Int32) -> Void { public func _bjs_getTheme() -> Void { #if arch(wasm32) let ret = getTheme() - var rawValue = ret.rawValue - return rawValue.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -36,13 +65,9 @@ public func _bjs_getTheme() -> Void { @_expose(wasm, "bjs_setTSTheme") @_cdecl("bjs_setTSTheme") -public func _bjs_setTSTheme(themeBytes: Int32, themeLen: Int32) -> Void { +public func _bjs_setTSTheme(themeBytes: Int32, themeLength: Int32) -> Void { #if arch(wasm32) - let theme = String(unsafeUninitializedCapacity: Int(themeLen)) { b in - _swift_js_init_memory(themeBytes, b.baseAddress.unsafelyUnwrapped) - return Int(themeLen) - } - setTSTheme(_: TSTheme(rawValue: theme)!) + setTSTheme(_: TSTheme.bridgeJSLiftParameter(themeBytes, themeLength)) #else fatalError("Only available on WebAssembly") #endif @@ -53,10 +78,7 @@ public func _bjs_setTSTheme(themeBytes: Int32, themeLen: Int32) -> Void { public func _bjs_getTSTheme() -> Void { #if arch(wasm32) let ret = getTSTheme() - var rawValue = ret.rawValue - return rawValue.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -66,7 +88,7 @@ public func _bjs_getTSTheme() -> Void { @_cdecl("bjs_setFeatureFlag") public func _bjs_setFeatureFlag(flag: Int32) -> Void { #if arch(wasm32) - setFeatureFlag(_: FeatureFlag(rawValue: flag != 0)!) + setFeatureFlag(_: FeatureFlag.bridgeJSLiftParameter(flag)) #else fatalError("Only available on WebAssembly") #endif @@ -77,7 +99,7 @@ public func _bjs_setFeatureFlag(flag: Int32) -> Void { public func _bjs_getFeatureFlag() -> Int32 { #if arch(wasm32) let ret = getFeatureFlag() - return Int32(ret.rawValue ? 1 : 0) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -87,7 +109,7 @@ public func _bjs_getFeatureFlag() -> Int32 { @_cdecl("bjs_setHttpStatus") public func _bjs_setHttpStatus(status: Int32) -> Void { #if arch(wasm32) - setHttpStatus(_: HttpStatus(rawValue: Int(status))!) + setHttpStatus(_: HttpStatus.bridgeJSLiftParameter(status)) #else fatalError("Only available on WebAssembly") #endif @@ -98,7 +120,7 @@ public func _bjs_setHttpStatus(status: Int32) -> Void { public func _bjs_getHttpStatus() -> Int32 { #if arch(wasm32) let ret = getHttpStatus() - return Int32(ret.rawValue) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -108,7 +130,7 @@ public func _bjs_getHttpStatus() -> Int32 { @_cdecl("bjs_setTSHttpStatus") public func _bjs_setTSHttpStatus(status: Int32) -> Void { #if arch(wasm32) - setTSHttpStatus(_: TSHttpStatus(rawValue: Int(status))!) + setTSHttpStatus(_: TSHttpStatus.bridgeJSLiftParameter(status)) #else fatalError("Only available on WebAssembly") #endif @@ -119,7 +141,7 @@ public func _bjs_setTSHttpStatus(status: Int32) -> Void { public func _bjs_getTSHttpStatus() -> Int32 { #if arch(wasm32) let ret = getTSHttpStatus() - return Int32(ret.rawValue) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -129,7 +151,7 @@ public func _bjs_getTSHttpStatus() -> Int32 { @_cdecl("bjs_setPriority") public func _bjs_setPriority(priority: Int32) -> Void { #if arch(wasm32) - setPriority(_: Priority(rawValue: Int32(priority))!) + setPriority(_: Priority.bridgeJSLiftParameter(priority)) #else fatalError("Only available on WebAssembly") #endif @@ -140,7 +162,7 @@ public func _bjs_setPriority(priority: Int32) -> Void { public func _bjs_getPriority() -> Int32 { #if arch(wasm32) let ret = getPriority() - return Int32(ret.rawValue) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -148,9 +170,9 @@ public func _bjs_getPriority() -> Int32 { @_expose(wasm, "bjs_setFileSize") @_cdecl("bjs_setFileSize") -public func _bjs_setFileSize(size: Int64) -> Void { +public func _bjs_setFileSize(size: Int32) -> Void { #if arch(wasm32) - setFileSize(_: FileSize(rawValue: Int64(size))!) + setFileSize(_: FileSize.bridgeJSLiftParameter(size)) #else fatalError("Only available on WebAssembly") #endif @@ -158,10 +180,10 @@ public func _bjs_setFileSize(size: Int64) -> Void { @_expose(wasm, "bjs_getFileSize") @_cdecl("bjs_getFileSize") -public func _bjs_getFileSize() -> Int64 { +public func _bjs_getFileSize() -> Int32 { #if arch(wasm32) let ret = getFileSize() - return Int64(ret.rawValue) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -171,7 +193,7 @@ public func _bjs_getFileSize() -> Int64 { @_cdecl("bjs_setUserId") public func _bjs_setUserId(id: Int32) -> Void { #if arch(wasm32) - setUserId(_: UserId(rawValue: UInt(bitPattern: id))!) + setUserId(_: UserId.bridgeJSLiftParameter(id)) #else fatalError("Only available on WebAssembly") #endif @@ -182,7 +204,7 @@ public func _bjs_setUserId(id: Int32) -> Void { public func _bjs_getUserId() -> Int32 { #if arch(wasm32) let ret = getUserId() - return Int32(ret.rawValue) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -192,7 +214,7 @@ public func _bjs_getUserId() -> Int32 { @_cdecl("bjs_setTokenId") public func _bjs_setTokenId(token: Int32) -> Void { #if arch(wasm32) - setTokenId(_: TokenId(rawValue: UInt32(bitPattern: token))!) + setTokenId(_: TokenId.bridgeJSLiftParameter(token)) #else fatalError("Only available on WebAssembly") #endif @@ -203,7 +225,7 @@ public func _bjs_setTokenId(token: Int32) -> Void { public func _bjs_getTokenId() -> Int32 { #if arch(wasm32) let ret = getTokenId() - return Int32(ret.rawValue) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -211,9 +233,9 @@ public func _bjs_getTokenId() -> Int32 { @_expose(wasm, "bjs_setSessionId") @_cdecl("bjs_setSessionId") -public func _bjs_setSessionId(session: Int64) -> Void { +public func _bjs_setSessionId(session: Int32) -> Void { #if arch(wasm32) - setSessionId(_: SessionId(rawValue: UInt64(bitPattern: Int64(session)))!) + setSessionId(_: SessionId.bridgeJSLiftParameter(session)) #else fatalError("Only available on WebAssembly") #endif @@ -221,10 +243,10 @@ public func _bjs_setSessionId(session: Int64) -> Void { @_expose(wasm, "bjs_getSessionId") @_cdecl("bjs_getSessionId") -public func _bjs_getSessionId() -> Int64 { +public func _bjs_getSessionId() -> Int32 { #if arch(wasm32) let ret = getSessionId() - return Int64(ret.rawValue) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -234,7 +256,7 @@ public func _bjs_getSessionId() -> Int64 { @_cdecl("bjs_setPrecision") public func _bjs_setPrecision(precision: Float32) -> Void { #if arch(wasm32) - setPrecision(_: Precision(rawValue: Float(precision))!) + setPrecision(_: Precision.bridgeJSLiftParameter(precision)) #else fatalError("Only available on WebAssembly") #endif @@ -245,7 +267,7 @@ public func _bjs_setPrecision(precision: Float32) -> Void { public func _bjs_getPrecision() -> Float32 { #if arch(wasm32) let ret = getPrecision() - return Float32(ret.rawValue) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -255,7 +277,7 @@ public func _bjs_getPrecision() -> Float32 { @_cdecl("bjs_setRatio") public func _bjs_setRatio(ratio: Float64) -> Void { #if arch(wasm32) - setRatio(_: Ratio(rawValue: Double(ratio))!) + setRatio(_: Ratio.bridgeJSLiftParameter(ratio)) #else fatalError("Only available on WebAssembly") #endif @@ -266,7 +288,7 @@ public func _bjs_setRatio(ratio: Float64) -> Void { public func _bjs_getRatio() -> Float64 { #if arch(wasm32) let ret = getRatio() - return Float64(ret.rawValue) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -276,7 +298,7 @@ public func _bjs_getRatio() -> Float64 { @_cdecl("bjs_setFeatureFlag") public func _bjs_setFeatureFlag(featureFlag: Int32) -> Void { #if arch(wasm32) - setFeatureFlag(_: FeatureFlag(rawValue: featureFlag != 0)!) + setFeatureFlag(_: FeatureFlag.bridgeJSLiftParameter(featureFlag)) #else fatalError("Only available on WebAssembly") #endif @@ -287,7 +309,7 @@ public func _bjs_setFeatureFlag(featureFlag: Int32) -> Void { public func _bjs_getFeatureFlag() -> Int32 { #if arch(wasm32) let ret = getFeatureFlag() - return Int32(ret.rawValue ? 1 : 0) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -295,14 +317,10 @@ public func _bjs_getFeatureFlag() -> Int32 { @_expose(wasm, "bjs_processTheme") @_cdecl("bjs_processTheme") -public func _bjs_processTheme(themeBytes: Int32, themeLen: Int32) -> Int32 { +public func _bjs_processTheme(themeBytes: Int32, themeLength: Int32) -> Int32 { #if arch(wasm32) - let theme = String(unsafeUninitializedCapacity: Int(themeLen)) { b in - _swift_js_init_memory(themeBytes, b.baseAddress.unsafelyUnwrapped) - return Int(themeLen) - } - let ret = processTheme(_: Theme(rawValue: theme)!) - return Int32(ret.rawValue) + let ret = processTheme(_: Theme.bridgeJSLiftParameter(themeBytes, themeLength)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -312,8 +330,8 @@ public func _bjs_processTheme(themeBytes: Int32, themeLen: Int32) -> Int32 { @_cdecl("bjs_convertPriority") public func _bjs_convertPriority(status: Int32) -> Int32 { #if arch(wasm32) - let ret = convertPriority(_: HttpStatus(rawValue: Int(status))!) - return Int32(ret.rawValue) + let ret = convertPriority(_: HttpStatus.bridgeJSLiftParameter(status)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -321,13 +339,10 @@ public func _bjs_convertPriority(status: Int32) -> Int32 { @_expose(wasm, "bjs_validateSession") @_cdecl("bjs_validateSession") -public func _bjs_validateSession(session: Int64) -> Void { +public func _bjs_validateSession(session: Int32) -> Void { #if arch(wasm32) - let ret = validateSession(_: SessionId(rawValue: UInt64(bitPattern: Int64(session)))!) - var rawValue = ret.rawValue - return rawValue.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = validateSession(_: SessionId.bridgeJSLiftParameter(session)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.swift index 21937c6c..f0e7f657 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.swift @@ -10,10 +10,8 @@ @_cdecl("bjs_plainFunction") public func _bjs_plainFunction() -> Void { #if arch(wasm32) - var ret = plainFunction() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = plainFunction() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -23,10 +21,8 @@ public func _bjs_plainFunction() -> Void { @_cdecl("bjs_namespacedFunction") public func _bjs_namespacedFunction() -> Void { #if arch(wasm32) - var ret = namespacedFunction() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = namespacedFunction() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -34,14 +30,10 @@ public func _bjs_namespacedFunction() -> Void { @_expose(wasm, "bjs_Greeter_init") @_cdecl("bjs_Greeter_init") -public func _bjs_Greeter_init(nameBytes: Int32, nameLen: Int32) -> UnsafeMutableRawPointer { +public func _bjs_Greeter_init(nameBytes: Int32, nameLength: Int32) -> UnsafeMutableRawPointer { #if arch(wasm32) - let name = String(unsafeUninitializedCapacity: Int(nameLen)) { b in - _swift_js_init_memory(nameBytes, b.baseAddress.unsafelyUnwrapped) - return Int(nameLen) - } - let ret = Greeter(name: name) - return Unmanaged.passRetained(ret).toOpaque() + let ret = Greeter(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -51,10 +43,8 @@ public func _bjs_Greeter_init(nameBytes: Int32, nameLen: Int32) -> UnsafeMutable @_cdecl("bjs_Greeter_greet") public func _bjs_Greeter_greet(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().greet() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = Greeter.bridgeJSLiftParameter(_self).greet() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -66,10 +56,16 @@ public func _bjs_Greeter_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension Greeter: ConvertibleToJSValue { +extension Greeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_Greeter_wrap") func _bjs_Greeter_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_Greeter_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_Greeter_wrap(Unmanaged.passRetained(self).toOpaque())))) } } @@ -79,7 +75,7 @@ extension Greeter: ConvertibleToJSValue { public func _bjs_Converter_init() -> UnsafeMutableRawPointer { #if arch(wasm32) let ret = Converter() - return Unmanaged.passRetained(ret).toOpaque() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -89,10 +85,8 @@ public func _bjs_Converter_init() -> UnsafeMutableRawPointer { @_cdecl("bjs_Converter_toString") public func _bjs_Converter_toString(_self: UnsafeMutableRawPointer, value: Int32) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().toString(value: Int(value)) - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = Converter.bridgeJSLiftParameter(_self).toString(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -104,10 +98,16 @@ public func _bjs_Converter_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension Converter: ConvertibleToJSValue { +extension Converter: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_Converter_wrap") func _bjs_Converter_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_Converter_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_Converter_wrap(Unmanaged.passRetained(self).toOpaque())))) } } @@ -116,10 +116,8 @@ extension Converter: ConvertibleToJSValue { @_cdecl("bjs_UUID_uuidString") public func _bjs_UUID_uuidString(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().uuidString() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = UUID.bridgeJSLiftParameter(_self).uuidString() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -131,10 +129,16 @@ public func _bjs_UUID_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension UUID: ConvertibleToJSValue { +extension UUID: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_UUID_wrap") func _bjs_UUID_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_UUID_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_UUID_wrap(Unmanaged.passRetained(self).toOpaque())))) } } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.swift index c686c426..33097726 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.swift @@ -10,7 +10,7 @@ @_cdecl("bjs_check") public func _bjs_check(a: Int32, b: Float32, c: Float64, d: Int32) -> Void { #if arch(wasm32) - check(a: Int(a), b: b, c: c, d: d == 1) + check(a: Int.bridgeJSLiftParameter(a), b: Float.bridgeJSLiftParameter(b), c: Double.bridgeJSLiftParameter(c), d: Bool.bridgeJSLiftParameter(d)) #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.swift index 7356f2c8..63e5f03c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.swift @@ -11,7 +11,7 @@ public func _bjs_checkInt() -> Int32 { #if arch(wasm32) let ret = checkInt() - return Int32(ret) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -22,7 +22,7 @@ public func _bjs_checkInt() -> Int32 { public func _bjs_checkFloat() -> Float32 { #if arch(wasm32) let ret = checkFloat() - return Float32(ret) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -33,7 +33,7 @@ public func _bjs_checkFloat() -> Float32 { public func _bjs_checkDouble() -> Float64 { #if arch(wasm32) let ret = checkDouble() - return Float64(ret) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -44,7 +44,7 @@ public func _bjs_checkDouble() -> Float64 { public func _bjs_checkBool() -> Int32 { #if arch(wasm32) let ret = checkBool() - return Int32(ret ? 1 : 0) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PropertyTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PropertyTypes.swift index 84609c74..822e5846 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PropertyTypes.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PropertyTypes.swift @@ -8,14 +8,10 @@ @_expose(wasm, "bjs_createPropertyHolder") @_cdecl("bjs_createPropertyHolder") -public func _bjs_createPropertyHolder(intValue: Int32, floatValue: Float32, doubleValue: Float64, boolValue: Int32, stringValueBytes: Int32, stringValueLen: Int32, jsObject: Int32) -> UnsafeMutableRawPointer { +public func _bjs_createPropertyHolder(intValue: Int32, floatValue: Float32, doubleValue: Float64, boolValue: Int32, stringValueBytes: Int32, stringValueLength: Int32, jsObject: Int32) -> UnsafeMutableRawPointer { #if arch(wasm32) - let stringValue = String(unsafeUninitializedCapacity: Int(stringValueLen)) { b in - _swift_js_init_memory(stringValueBytes, b.baseAddress.unsafelyUnwrapped) - return Int(stringValueLen) - } - let ret = createPropertyHolder(intValue: Int(intValue), floatValue: floatValue, doubleValue: doubleValue, boolValue: boolValue == 1, stringValue: stringValue, jsObject: JSObject(id: UInt32(bitPattern: jsObject))) - return Unmanaged.passRetained(ret).toOpaque() + let ret = createPropertyHolder(intValue: Int.bridgeJSLiftParameter(intValue), floatValue: Float.bridgeJSLiftParameter(floatValue), doubleValue: Double.bridgeJSLiftParameter(doubleValue), boolValue: Bool.bridgeJSLiftParameter(boolValue), stringValue: String.bridgeJSLiftParameter(stringValueBytes, stringValueLength), jsObject: JSObject.bridgeJSLiftParameter(jsObject)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -25,10 +21,8 @@ public func _bjs_createPropertyHolder(intValue: Int32, floatValue: Float32, doub @_cdecl("bjs_testPropertyHolder") public func _bjs_testPropertyHolder(holder: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = testPropertyHolder(holder: Unmanaged.fromOpaque(holder).takeUnretainedValue()) - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = testPropertyHolder(holder: PropertyHolder.bridgeJSLiftParameter(holder)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -36,14 +30,10 @@ public func _bjs_testPropertyHolder(holder: UnsafeMutableRawPointer) -> Void { @_expose(wasm, "bjs_PropertyHolder_init") @_cdecl("bjs_PropertyHolder_init") -public func _bjs_PropertyHolder_init(intValue: Int32, floatValue: Float32, doubleValue: Float64, boolValue: Int32, stringValueBytes: Int32, stringValueLen: Int32, jsObject: Int32) -> UnsafeMutableRawPointer { +public func _bjs_PropertyHolder_init(intValue: Int32, floatValue: Float32, doubleValue: Float64, boolValue: Int32, stringValueBytes: Int32, stringValueLength: Int32, jsObject: Int32) -> UnsafeMutableRawPointer { #if arch(wasm32) - let stringValue = String(unsafeUninitializedCapacity: Int(stringValueLen)) { b in - _swift_js_init_memory(stringValueBytes, b.baseAddress.unsafelyUnwrapped) - return Int(stringValueLen) - } - let ret = PropertyHolder(intValue: Int(intValue), floatValue: floatValue, doubleValue: doubleValue, boolValue: boolValue == 1, stringValue: stringValue, jsObject: JSObject(id: UInt32(bitPattern: jsObject))) - return Unmanaged.passRetained(ret).toOpaque() + let ret = PropertyHolder(intValue: Int.bridgeJSLiftParameter(intValue), floatValue: Float.bridgeJSLiftParameter(floatValue), doubleValue: Double.bridgeJSLiftParameter(doubleValue), boolValue: Bool.bridgeJSLiftParameter(boolValue), stringValue: String.bridgeJSLiftParameter(stringValueBytes, stringValueLength), jsObject: JSObject.bridgeJSLiftParameter(jsObject)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -53,10 +43,8 @@ public func _bjs_PropertyHolder_init(intValue: Int32, floatValue: Float32, doubl @_cdecl("bjs_PropertyHolder_getAllValues") public func _bjs_PropertyHolder_getAllValues(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().getAllValues() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = PropertyHolder.bridgeJSLiftParameter(_self).getAllValues() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -66,8 +54,8 @@ public func _bjs_PropertyHolder_getAllValues(_self: UnsafeMutableRawPointer) -> @_cdecl("bjs_PropertyHolder_intValue_get") public func _bjs_PropertyHolder_intValue_get(_self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().intValue - return Int32(ret) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).intValue + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -77,7 +65,7 @@ public func _bjs_PropertyHolder_intValue_get(_self: UnsafeMutableRawPointer) -> @_cdecl("bjs_PropertyHolder_intValue_set") public func _bjs_PropertyHolder_intValue_set(_self: UnsafeMutableRawPointer, value: Int32) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().intValue = Int(value) + PropertyHolder.bridgeJSLiftParameter(_self).intValue = Int.bridgeJSLiftParameter(value) #else fatalError("Only available on WebAssembly") #endif @@ -87,8 +75,8 @@ public func _bjs_PropertyHolder_intValue_set(_self: UnsafeMutableRawPointer, val @_cdecl("bjs_PropertyHolder_floatValue_get") public func _bjs_PropertyHolder_floatValue_get(_self: UnsafeMutableRawPointer) -> Float32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().floatValue - return Float32(ret) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).floatValue + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -98,7 +86,7 @@ public func _bjs_PropertyHolder_floatValue_get(_self: UnsafeMutableRawPointer) - @_cdecl("bjs_PropertyHolder_floatValue_set") public func _bjs_PropertyHolder_floatValue_set(_self: UnsafeMutableRawPointer, value: Float32) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().floatValue = value + PropertyHolder.bridgeJSLiftParameter(_self).floatValue = Float.bridgeJSLiftParameter(value) #else fatalError("Only available on WebAssembly") #endif @@ -108,8 +96,8 @@ public func _bjs_PropertyHolder_floatValue_set(_self: UnsafeMutableRawPointer, v @_cdecl("bjs_PropertyHolder_doubleValue_get") public func _bjs_PropertyHolder_doubleValue_get(_self: UnsafeMutableRawPointer) -> Float64 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().doubleValue - return Float64(ret) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).doubleValue + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -119,7 +107,7 @@ public func _bjs_PropertyHolder_doubleValue_get(_self: UnsafeMutableRawPointer) @_cdecl("bjs_PropertyHolder_doubleValue_set") public func _bjs_PropertyHolder_doubleValue_set(_self: UnsafeMutableRawPointer, value: Float64) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().doubleValue = value + PropertyHolder.bridgeJSLiftParameter(_self).doubleValue = Double.bridgeJSLiftParameter(value) #else fatalError("Only available on WebAssembly") #endif @@ -129,8 +117,8 @@ public func _bjs_PropertyHolder_doubleValue_set(_self: UnsafeMutableRawPointer, @_cdecl("bjs_PropertyHolder_boolValue_get") public func _bjs_PropertyHolder_boolValue_get(_self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().boolValue - return Int32(ret ? 1 : 0) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).boolValue + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -140,7 +128,7 @@ public func _bjs_PropertyHolder_boolValue_get(_self: UnsafeMutableRawPointer) -> @_cdecl("bjs_PropertyHolder_boolValue_set") public func _bjs_PropertyHolder_boolValue_set(_self: UnsafeMutableRawPointer, value: Int32) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().boolValue = value == 1 + PropertyHolder.bridgeJSLiftParameter(_self).boolValue = Bool.bridgeJSLiftParameter(value) #else fatalError("Only available on WebAssembly") #endif @@ -150,10 +138,8 @@ public func _bjs_PropertyHolder_boolValue_set(_self: UnsafeMutableRawPointer, va @_cdecl("bjs_PropertyHolder_stringValue_get") public func _bjs_PropertyHolder_stringValue_get(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().stringValue - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = PropertyHolder.bridgeJSLiftParameter(_self).stringValue + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -161,13 +147,9 @@ public func _bjs_PropertyHolder_stringValue_get(_self: UnsafeMutableRawPointer) @_expose(wasm, "bjs_PropertyHolder_stringValue_set") @_cdecl("bjs_PropertyHolder_stringValue_set") -public func _bjs_PropertyHolder_stringValue_set(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLen: Int32) -> Void { +public func _bjs_PropertyHolder_stringValue_set(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLength: Int32) -> Void { #if arch(wasm32) - let value = String(unsafeUninitializedCapacity: Int(valueLen)) { b in - _swift_js_init_memory(valueBytes, b.baseAddress.unsafelyUnwrapped) - return Int(valueLen) - } - Unmanaged.fromOpaque(_self).takeUnretainedValue().stringValue = value + PropertyHolder.bridgeJSLiftParameter(_self).stringValue = String.bridgeJSLiftParameter(valueBytes, valueLength) #else fatalError("Only available on WebAssembly") #endif @@ -177,8 +159,8 @@ public func _bjs_PropertyHolder_stringValue_set(_self: UnsafeMutableRawPointer, @_cdecl("bjs_PropertyHolder_readonlyInt_get") public func _bjs_PropertyHolder_readonlyInt_get(_self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().readonlyInt - return Int32(ret) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyInt + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -188,8 +170,8 @@ public func _bjs_PropertyHolder_readonlyInt_get(_self: UnsafeMutableRawPointer) @_cdecl("bjs_PropertyHolder_readonlyFloat_get") public func _bjs_PropertyHolder_readonlyFloat_get(_self: UnsafeMutableRawPointer) -> Float32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().readonlyFloat - return Float32(ret) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyFloat + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -199,8 +181,8 @@ public func _bjs_PropertyHolder_readonlyFloat_get(_self: UnsafeMutableRawPointer @_cdecl("bjs_PropertyHolder_readonlyDouble_get") public func _bjs_PropertyHolder_readonlyDouble_get(_self: UnsafeMutableRawPointer) -> Float64 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().readonlyDouble - return Float64(ret) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyDouble + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -210,8 +192,8 @@ public func _bjs_PropertyHolder_readonlyDouble_get(_self: UnsafeMutableRawPointe @_cdecl("bjs_PropertyHolder_readonlyBool_get") public func _bjs_PropertyHolder_readonlyBool_get(_self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().readonlyBool - return Int32(ret ? 1 : 0) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyBool + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -221,10 +203,8 @@ public func _bjs_PropertyHolder_readonlyBool_get(_self: UnsafeMutableRawPointer) @_cdecl("bjs_PropertyHolder_readonlyString_get") public func _bjs_PropertyHolder_readonlyString_get(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().readonlyString - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyString + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -234,8 +214,8 @@ public func _bjs_PropertyHolder_readonlyString_get(_self: UnsafeMutableRawPointe @_cdecl("bjs_PropertyHolder_jsObject_get") public func _bjs_PropertyHolder_jsObject_get(_self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).jsObject + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -245,7 +225,7 @@ public func _bjs_PropertyHolder_jsObject_get(_self: UnsafeMutableRawPointer) -> @_cdecl("bjs_PropertyHolder_jsObject_set") public func _bjs_PropertyHolder_jsObject_set(_self: UnsafeMutableRawPointer, value: Int32) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().jsObject = JSObject(id: UInt32(bitPattern: value)) + PropertyHolder.bridgeJSLiftParameter(_self).jsObject = JSObject.bridgeJSLiftParameter(value) #else fatalError("Only available on WebAssembly") #endif @@ -255,8 +235,8 @@ public func _bjs_PropertyHolder_jsObject_set(_self: UnsafeMutableRawPointer, val @_cdecl("bjs_PropertyHolder_sibling_get") public func _bjs_PropertyHolder_sibling_get(_self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().sibling - return Unmanaged.passRetained(ret).toOpaque() + let ret = PropertyHolder.bridgeJSLiftParameter(_self).sibling + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -266,7 +246,7 @@ public func _bjs_PropertyHolder_sibling_get(_self: UnsafeMutableRawPointer) -> U @_cdecl("bjs_PropertyHolder_sibling_set") public func _bjs_PropertyHolder_sibling_set(_self: UnsafeMutableRawPointer, value: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().sibling = Unmanaged.fromOpaque(value).takeUnretainedValue() + PropertyHolder.bridgeJSLiftParameter(_self).sibling = PropertyHolder.bridgeJSLiftParameter(value) #else fatalError("Only available on WebAssembly") #endif @@ -276,10 +256,8 @@ public func _bjs_PropertyHolder_sibling_set(_self: UnsafeMutableRawPointer, valu @_cdecl("bjs_PropertyHolder_lazyValue_get") public func _bjs_PropertyHolder_lazyValue_get(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().lazyValue - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = PropertyHolder.bridgeJSLiftParameter(_self).lazyValue + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -287,13 +265,9 @@ public func _bjs_PropertyHolder_lazyValue_get(_self: UnsafeMutableRawPointer) -> @_expose(wasm, "bjs_PropertyHolder_lazyValue_set") @_cdecl("bjs_PropertyHolder_lazyValue_set") -public func _bjs_PropertyHolder_lazyValue_set(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLen: Int32) -> Void { +public func _bjs_PropertyHolder_lazyValue_set(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLength: Int32) -> Void { #if arch(wasm32) - let value = String(unsafeUninitializedCapacity: Int(valueLen)) { b in - _swift_js_init_memory(valueBytes, b.baseAddress.unsafelyUnwrapped) - return Int(valueLen) - } - Unmanaged.fromOpaque(_self).takeUnretainedValue().lazyValue = value + PropertyHolder.bridgeJSLiftParameter(_self).lazyValue = String.bridgeJSLiftParameter(valueBytes, valueLength) #else fatalError("Only available on WebAssembly") #endif @@ -303,8 +277,8 @@ public func _bjs_PropertyHolder_lazyValue_set(_self: UnsafeMutableRawPointer, va @_cdecl("bjs_PropertyHolder_computedReadonly_get") public func _bjs_PropertyHolder_computedReadonly_get(_self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().computedReadonly - return Int32(ret) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).computedReadonly + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -314,10 +288,8 @@ public func _bjs_PropertyHolder_computedReadonly_get(_self: UnsafeMutableRawPoin @_cdecl("bjs_PropertyHolder_computedReadWrite_get") public func _bjs_PropertyHolder_computedReadWrite_get(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().computedReadWrite - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = PropertyHolder.bridgeJSLiftParameter(_self).computedReadWrite + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -325,13 +297,9 @@ public func _bjs_PropertyHolder_computedReadWrite_get(_self: UnsafeMutableRawPoi @_expose(wasm, "bjs_PropertyHolder_computedReadWrite_set") @_cdecl("bjs_PropertyHolder_computedReadWrite_set") -public func _bjs_PropertyHolder_computedReadWrite_set(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLen: Int32) -> Void { +public func _bjs_PropertyHolder_computedReadWrite_set(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLength: Int32) -> Void { #if arch(wasm32) - let value = String(unsafeUninitializedCapacity: Int(valueLen)) { b in - _swift_js_init_memory(valueBytes, b.baseAddress.unsafelyUnwrapped) - return Int(valueLen) - } - Unmanaged.fromOpaque(_self).takeUnretainedValue().computedReadWrite = value + PropertyHolder.bridgeJSLiftParameter(_self).computedReadWrite = String.bridgeJSLiftParameter(valueBytes, valueLength) #else fatalError("Only available on WebAssembly") #endif @@ -341,8 +309,8 @@ public func _bjs_PropertyHolder_computedReadWrite_set(_self: UnsafeMutableRawPoi @_cdecl("bjs_PropertyHolder_observedProperty_get") public func _bjs_PropertyHolder_observedProperty_get(_self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().observedProperty - return Int32(ret) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).observedProperty + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -352,7 +320,7 @@ public func _bjs_PropertyHolder_observedProperty_get(_self: UnsafeMutableRawPoin @_cdecl("bjs_PropertyHolder_observedProperty_set") public func _bjs_PropertyHolder_observedProperty_set(_self: UnsafeMutableRawPointer, value: Int32) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().observedProperty = Int(value) + PropertyHolder.bridgeJSLiftParameter(_self).observedProperty = Int.bridgeJSLiftParameter(value) #else fatalError("Only available on WebAssembly") #endif @@ -364,10 +332,16 @@ public func _bjs_PropertyHolder_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension PropertyHolder: ConvertibleToJSValue { +extension PropertyHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_PropertyHolder_wrap") func _bjs_PropertyHolder_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_PropertyHolder_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_PropertyHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) } } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.swift index 69bd66b5..723a639c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.swift @@ -8,13 +8,9 @@ @_expose(wasm, "bjs_checkString") @_cdecl("bjs_checkString") -public func _bjs_checkString(aBytes: Int32, aLen: Int32) -> Void { +public func _bjs_checkString(aBytes: Int32, aLength: Int32) -> Void { #if arch(wasm32) - let a = String(unsafeUninitializedCapacity: Int(aLen)) { b in - _swift_js_init_memory(aBytes, b.baseAddress.unsafelyUnwrapped) - return Int(aLen) - } - checkString(a: a) + checkString(a: String.bridgeJSLiftParameter(aBytes, aLength)) #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringReturn.swift index 536f0623..0475def5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringReturn.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringReturn.swift @@ -10,10 +10,8 @@ @_cdecl("bjs_checkString") public func _bjs_checkString() -> Void { #if arch(wasm32) - var ret = checkString() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = checkString() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClass.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClass.swift index bcb9f3d7..5a354b43 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClass.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClass.swift @@ -10,7 +10,7 @@ @_cdecl("bjs_takeGreeter") public func _bjs_takeGreeter(greeter: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - takeGreeter(greeter: Unmanaged.fromOpaque(greeter).takeUnretainedValue()) + takeGreeter(greeter: Greeter.bridgeJSLiftParameter(greeter)) #else fatalError("Only available on WebAssembly") #endif @@ -18,14 +18,10 @@ public func _bjs_takeGreeter(greeter: UnsafeMutableRawPointer) -> Void { @_expose(wasm, "bjs_Greeter_init") @_cdecl("bjs_Greeter_init") -public func _bjs_Greeter_init(nameBytes: Int32, nameLen: Int32) -> UnsafeMutableRawPointer { +public func _bjs_Greeter_init(nameBytes: Int32, nameLength: Int32) -> UnsafeMutableRawPointer { #if arch(wasm32) - let name = String(unsafeUninitializedCapacity: Int(nameLen)) { b in - _swift_js_init_memory(nameBytes, b.baseAddress.unsafelyUnwrapped) - return Int(nameLen) - } - let ret = Greeter(name: name) - return Unmanaged.passRetained(ret).toOpaque() + let ret = Greeter(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -35,10 +31,8 @@ public func _bjs_Greeter_init(nameBytes: Int32, nameLen: Int32) -> UnsafeMutable @_cdecl("bjs_Greeter_greet") public func _bjs_Greeter_greet(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().greet() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = Greeter.bridgeJSLiftParameter(_self).greet() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -46,13 +40,9 @@ public func _bjs_Greeter_greet(_self: UnsafeMutableRawPointer) -> Void { @_expose(wasm, "bjs_Greeter_changeName") @_cdecl("bjs_Greeter_changeName") -public func _bjs_Greeter_changeName(_self: UnsafeMutableRawPointer, nameBytes: Int32, nameLen: Int32) -> Void { +public func _bjs_Greeter_changeName(_self: UnsafeMutableRawPointer, nameBytes: Int32, nameLength: Int32) -> Void { #if arch(wasm32) - let name = String(unsafeUninitializedCapacity: Int(nameLen)) { b in - _swift_js_init_memory(nameBytes, b.baseAddress.unsafelyUnwrapped) - return Int(nameLen) - } - Unmanaged.fromOpaque(_self).takeUnretainedValue().changeName(name: name) + Greeter.bridgeJSLiftParameter(_self).changeName(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) #else fatalError("Only available on WebAssembly") #endif @@ -62,10 +52,8 @@ public func _bjs_Greeter_changeName(_self: UnsafeMutableRawPointer, nameBytes: I @_cdecl("bjs_Greeter_name_get") public func _bjs_Greeter_name_get(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().name - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = Greeter.bridgeJSLiftParameter(_self).name + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -73,13 +61,9 @@ public func _bjs_Greeter_name_get(_self: UnsafeMutableRawPointer) -> Void { @_expose(wasm, "bjs_Greeter_name_set") @_cdecl("bjs_Greeter_name_set") -public func _bjs_Greeter_name_set(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLen: Int32) -> Void { +public func _bjs_Greeter_name_set(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLength: Int32) -> Void { #if arch(wasm32) - let value = String(unsafeUninitializedCapacity: Int(valueLen)) { b in - _swift_js_init_memory(valueBytes, b.baseAddress.unsafelyUnwrapped) - return Int(valueLen) - } - Unmanaged.fromOpaque(_self).takeUnretainedValue().name = value + Greeter.bridgeJSLiftParameter(_self).name = String.bridgeJSLiftParameter(valueBytes, valueLength) #else fatalError("Only available on WebAssembly") #endif @@ -91,10 +75,16 @@ public func _bjs_Greeter_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension Greeter: ConvertibleToJSValue { +extension Greeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_Greeter_wrap") func _bjs_Greeter_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_Greeter_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_Greeter_wrap(Unmanaged.passRetained(self).toOpaque())))) } } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/ArrayParameter.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/ArrayParameter.swift index 34841ae8..96fac13d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/ArrayParameter.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/ArrayParameter.swift @@ -15,7 +15,7 @@ func checkArray(_ a: JSObject) throws(JSException) -> Void { fatalError("Only available on WebAssembly") } #endif - bjs_checkArray(Int32(bitPattern: a.id)) + bjs_checkArray(a.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } @@ -30,7 +30,7 @@ func checkArrayWithLength(_ a: JSObject, _ b: Double) throws(JSException) -> Voi fatalError("Only available on WebAssembly") } #endif - bjs_checkArrayWithLength(Int32(bitPattern: a.id), b) + bjs_checkArrayWithLength(a.bridgeJSLowerParameter(), b.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } @@ -45,7 +45,7 @@ func checkArray(_ a: JSObject) throws(JSException) -> Void { fatalError("Only available on WebAssembly") } #endif - bjs_checkArray(Int32(bitPattern: a.id)) + bjs_checkArray(a.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/Async.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/Async.swift index aa11cd0c..a8ecf8d5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/Async.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/Async.swift @@ -19,7 +19,7 @@ func asyncReturnVoid() throws(JSException) -> JSPromise { if let error = _swift_js_take_exception() { throw error } - return JSPromise(takingThis: ret) + return JSPromise.bridgeJSLiftReturn(ret) } func asyncRoundTripInt(_ v: Double) throws(JSException) -> JSPromise { @@ -31,11 +31,11 @@ func asyncRoundTripInt(_ v: Double) throws(JSException) -> JSPromise { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_asyncRoundTripInt(v) + let ret = bjs_asyncRoundTripInt(v.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return JSPromise(takingThis: ret) + return JSPromise.bridgeJSLiftReturn(ret) } func asyncRoundTripString(_ v: String) throws(JSException) -> JSPromise { @@ -47,15 +47,11 @@ func asyncRoundTripString(_ v: String) throws(JSException) -> JSPromise { fatalError("Only available on WebAssembly") } #endif - var v = v - let vId = v.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_asyncRoundTripString(vId) + let ret = bjs_asyncRoundTripString(v.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return JSPromise(takingThis: ret) + return JSPromise.bridgeJSLiftReturn(ret) } func asyncRoundTripBool(_ v: Bool) throws(JSException) -> JSPromise { @@ -67,11 +63,11 @@ func asyncRoundTripBool(_ v: Bool) throws(JSException) -> JSPromise { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_asyncRoundTripBool(Int32(v ? 1 : 0)) + let ret = bjs_asyncRoundTripBool(v.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return JSPromise(takingThis: ret) + return JSPromise.bridgeJSLiftReturn(ret) } func asyncRoundTripFloat(_ v: Double) throws(JSException) -> JSPromise { @@ -83,11 +79,11 @@ func asyncRoundTripFloat(_ v: Double) throws(JSException) -> JSPromise { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_asyncRoundTripFloat(v) + let ret = bjs_asyncRoundTripFloat(v.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return JSPromise(takingThis: ret) + return JSPromise.bridgeJSLiftReturn(ret) } func asyncRoundTripDouble(_ v: Double) throws(JSException) -> JSPromise { @@ -99,11 +95,11 @@ func asyncRoundTripDouble(_ v: Double) throws(JSException) -> JSPromise { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_asyncRoundTripDouble(v) + let ret = bjs_asyncRoundTripDouble(v.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return JSPromise(takingThis: ret) + return JSPromise.bridgeJSLiftReturn(ret) } func asyncRoundTripJSObject(_ v: JSObject) throws(JSException) -> JSPromise { @@ -115,9 +111,9 @@ func asyncRoundTripJSObject(_ v: JSObject) throws(JSException) -> JSPromise { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_asyncRoundTripJSObject(Int32(bitPattern: v.id)) + let ret = bjs_asyncRoundTripJSObject(v.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return JSPromise(takingThis: ret) + return JSPromise.bridgeJSLiftReturn(ret) } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/Interface.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/Interface.swift index be9f524e..68f14808 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/Interface.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/Interface.swift @@ -19,18 +19,14 @@ func returnAnimatable() throws(JSException) -> Animatable { if let error = _swift_js_take_exception() { throw error } - return Animatable(takingThis: ret) + return Animatable.bridgeJSLiftReturn(ret) } -struct Animatable { - let this: JSObject +struct Animatable: _JSBridgedClass { + let jsObject: JSObject - init(this: JSObject) { - self.this = this - } - - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject } func animate(_ keyframes: JSObject, _ options: JSObject) throws(JSException) -> JSObject { @@ -42,11 +38,11 @@ struct Animatable { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_Animatable_animate(Int32(bitPattern: self.this.id), Int32(bitPattern: keyframes.id), Int32(bitPattern: options.id)) + let ret = bjs_Animatable_animate(self.bridgeJSLowerParameter(), keyframes.bridgeJSLowerParameter(), options.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return JSObject(id: UInt32(bitPattern: ret)) + return JSObject.bridgeJSLiftReturn(ret) } func getAnimations(_ options: JSObject) throws(JSException) -> JSObject { @@ -58,11 +54,11 @@ struct Animatable { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_Animatable_getAnimations(Int32(bitPattern: self.this.id), Int32(bitPattern: options.id)) + let ret = bjs_Animatable_getAnimations(self.bridgeJSLowerParameter(), options.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return JSObject(id: UInt32(bitPattern: ret)) + return JSObject.bridgeJSLiftReturn(ret) } } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/MultipleImportedTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/MultipleImportedTypes.swift index d3e06e81..810df368 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/MultipleImportedTypes.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/MultipleImportedTypes.swift @@ -15,11 +15,11 @@ func createDatabaseConnection(_ config: JSObject) throws(JSException) -> Databas fatalError("Only available on WebAssembly") } #endif - let ret = bjs_createDatabaseConnection(Int32(bitPattern: config.id)) + let ret = bjs_createDatabaseConnection(config.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return DatabaseConnection(takingThis: ret) + return DatabaseConnection.bridgeJSLiftReturn(ret) } func createLogger(_ level: String) throws(JSException) -> Logger { @@ -31,15 +31,11 @@ func createLogger(_ level: String) throws(JSException) -> Logger { fatalError("Only available on WebAssembly") } #endif - var level = level - let levelId = level.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_createLogger(levelId) + let ret = bjs_createLogger(level.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return Logger(takingThis: ret) + return Logger.bridgeJSLiftReturn(ret) } func getConfigManager() throws(JSException) -> ConfigManager { @@ -55,18 +51,14 @@ func getConfigManager() throws(JSException) -> ConfigManager { if let error = _swift_js_take_exception() { throw error } - return ConfigManager(takingThis: ret) + return ConfigManager.bridgeJSLiftReturn(ret) } -struct DatabaseConnection { - let this: JSObject - - init(this: JSObject) { - self.this = this - } +struct DatabaseConnection: _JSBridgedClass { + let jsObject: JSObject - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject } var isConnected: Bool { @@ -79,11 +71,11 @@ struct DatabaseConnection { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_DatabaseConnection_isConnected_get(Int32(bitPattern: self.this.id)) + let ret = bjs_DatabaseConnection_isConnected_get(self.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return ret == 1 + return Bool.bridgeJSLiftReturn(ret) } } @@ -97,11 +89,11 @@ struct DatabaseConnection { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_DatabaseConnection_connectionTimeout_get(Int32(bitPattern: self.this.id)) + let ret = bjs_DatabaseConnection_connectionTimeout_get(self.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return Double(ret) + return Double.bridgeJSLiftReturn(ret) } } @@ -114,7 +106,7 @@ struct DatabaseConnection { fatalError("Only available on WebAssembly") } #endif - bjs_DatabaseConnection_connectionTimeout_set(Int32(bitPattern: self.this.id), newValue) + bjs_DatabaseConnection_connectionTimeout_set(self.bridgeJSLowerParameter(), newValue.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } @@ -129,11 +121,7 @@ struct DatabaseConnection { fatalError("Only available on WebAssembly") } #endif - var url = url - let urlId = url.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_DatabaseConnection_connect(Int32(bitPattern: self.this.id), urlId) + bjs_DatabaseConnection_connect(self.bridgeJSLowerParameter(), url.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } @@ -148,28 +136,20 @@ struct DatabaseConnection { fatalError("Only available on WebAssembly") } #endif - var query = query - let queryId = query.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_DatabaseConnection_execute(Int32(bitPattern: self.this.id), queryId) + let ret = bjs_DatabaseConnection_execute(self.bridgeJSLowerParameter(), query.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return JSObject(id: UInt32(bitPattern: ret)) + return JSObject.bridgeJSLiftReturn(ret) } } -struct Logger { - let this: JSObject - - init(this: JSObject) { - self.this = this - } +struct Logger: _JSBridgedClass { + let jsObject: JSObject - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject } var level: String { @@ -182,14 +162,11 @@ struct Logger { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_Logger_level_get(Int32(bitPattern: self.this.id)) + let ret = bjs_Logger_level_get(self.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } + return String.bridgeJSLiftReturn(ret) } } @@ -202,11 +179,7 @@ struct Logger { fatalError("Only available on WebAssembly") } #endif - var message = message - let messageId = message.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_Logger_log(Int32(bitPattern: self.this.id), messageId) + bjs_Logger_log(self.bridgeJSLowerParameter(), message.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } @@ -221,11 +194,7 @@ struct Logger { fatalError("Only available on WebAssembly") } #endif - var message = message - let messageId = message.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_Logger_error(Int32(bitPattern: self.this.id), messageId, Int32(bitPattern: error.id)) + bjs_Logger_error(self.bridgeJSLowerParameter(), message.bridgeJSLowerParameter(), error.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } @@ -233,15 +202,11 @@ struct Logger { } -struct ConfigManager { - let this: JSObject - - init(this: JSObject) { - self.this = this - } +struct ConfigManager: _JSBridgedClass { + let jsObject: JSObject - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject } var configPath: String { @@ -254,14 +219,11 @@ struct ConfigManager { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_ConfigManager_configPath_get(Int32(bitPattern: self.this.id)) + let ret = bjs_ConfigManager_configPath_get(self.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } + return String.bridgeJSLiftReturn(ret) } } @@ -274,15 +236,11 @@ struct ConfigManager { fatalError("Only available on WebAssembly") } #endif - var key = key - let keyId = key.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_ConfigManager_get(Int32(bitPattern: self.this.id), keyId) + let ret = bjs_ConfigManager_get(self.bridgeJSLowerParameter(), key.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return JSObject(id: UInt32(bitPattern: ret)) + return JSObject.bridgeJSLiftReturn(ret) } func set(_ key: String, _ value: JSObject) throws(JSException) -> Void { @@ -294,11 +252,7 @@ struct ConfigManager { fatalError("Only available on WebAssembly") } #endif - var key = key - let keyId = key.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_ConfigManager_set(Int32(bitPattern: self.this.id), keyId, Int32(bitPattern: value.id)) + bjs_ConfigManager_set(self.bridgeJSLowerParameter(), key.bridgeJSLowerParameter(), value.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/PrimitiveParameters.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/PrimitiveParameters.swift index c47f5f40..30f66a26 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/PrimitiveParameters.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/PrimitiveParameters.swift @@ -15,7 +15,7 @@ func check(_ a: Double, _ b: Bool) throws(JSException) -> Void { fatalError("Only available on WebAssembly") } #endif - bjs_check(a, Int32(b ? 1 : 0)) + bjs_check(a.bridgeJSLowerParameter(), b.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/PrimitiveReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/PrimitiveReturn.swift index cf26a52f..29ba81c6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/PrimitiveReturn.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/PrimitiveReturn.swift @@ -19,7 +19,7 @@ func checkNumber() throws(JSException) -> Double { if let error = _swift_js_take_exception() { throw error } - return Double(ret) + return Double.bridgeJSLiftReturn(ret) } func checkBoolean() throws(JSException) -> Bool { @@ -35,5 +35,5 @@ func checkBoolean() throws(JSException) -> Bool { if let error = _swift_js_take_exception() { throw error } - return ret == 1 + return Bool.bridgeJSLiftReturn(ret) } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/StringParameter.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/StringParameter.swift index aabffacc..99215a30 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/StringParameter.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/StringParameter.swift @@ -15,11 +15,7 @@ func checkString(_ a: String) throws(JSException) -> Void { fatalError("Only available on WebAssembly") } #endif - var a = a - let aId = a.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_checkString(aId) + bjs_checkString(a.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } @@ -34,11 +30,7 @@ func checkStringWithLength(_ a: String, _ b: Double) throws(JSException) -> Void fatalError("Only available on WebAssembly") } #endif - var a = a - let aId = a.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_checkStringWithLength(aId, b) + bjs_checkStringWithLength(a.bridgeJSLowerParameter(), b.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/StringReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/StringReturn.swift index af7b5162..05bb8aea 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/StringReturn.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/StringReturn.swift @@ -19,8 +19,5 @@ func checkString() throws(JSException) -> String { if let error = _swift_js_take_exception() { throw error } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } + return String.bridgeJSLiftReturn(ret) } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TS2SkeletonLike.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TS2SkeletonLike.swift index 95e9da8c..0b17f13b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TS2SkeletonLike.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TS2SkeletonLike.swift @@ -19,7 +19,7 @@ func createTS2Skeleton() throws(JSException) -> TypeScriptProcessor { if let error = _swift_js_take_exception() { throw error } - return TypeScriptProcessor(takingThis: ret) + return TypeScriptProcessor.bridgeJSLiftReturn(ret) } func createCodeGenerator(_ format: String) throws(JSException) -> CodeGenerator { @@ -31,26 +31,18 @@ func createCodeGenerator(_ format: String) throws(JSException) -> CodeGenerator fatalError("Only available on WebAssembly") } #endif - var format = format - let formatId = format.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_createCodeGenerator(formatId) + let ret = bjs_createCodeGenerator(format.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return CodeGenerator(takingThis: ret) + return CodeGenerator.bridgeJSLiftReturn(ret) } -struct TypeScriptProcessor { - let this: JSObject - - init(this: JSObject) { - self.this = this - } +struct TypeScriptProcessor: _JSBridgedClass { + let jsObject: JSObject - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject } var version: String { @@ -63,14 +55,11 @@ struct TypeScriptProcessor { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_TypeScriptProcessor_version_get(Int32(bitPattern: self.this.id)) + let ret = bjs_TypeScriptProcessor_version_get(self.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } + return String.bridgeJSLiftReturn(ret) } } @@ -83,18 +72,11 @@ struct TypeScriptProcessor { fatalError("Only available on WebAssembly") } #endif - var ts = ts - let tsId = ts.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_TypeScriptProcessor_convert(Int32(bitPattern: self.this.id), tsId) + let ret = bjs_TypeScriptProcessor_convert(self.bridgeJSLowerParameter(), ts.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } + return String.bridgeJSLiftReturn(ret) } func validate(_ ts: String) throws(JSException) -> Bool { @@ -106,28 +88,20 @@ struct TypeScriptProcessor { fatalError("Only available on WebAssembly") } #endif - var ts = ts - let tsId = ts.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_TypeScriptProcessor_validate(Int32(bitPattern: self.this.id), tsId) + let ret = bjs_TypeScriptProcessor_validate(self.bridgeJSLowerParameter(), ts.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return ret == 1 + return Bool.bridgeJSLiftReturn(ret) } } -struct CodeGenerator { - let this: JSObject - - init(this: JSObject) { - self.this = this - } +struct CodeGenerator: _JSBridgedClass { + let jsObject: JSObject - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject } var outputFormat: String { @@ -140,14 +114,11 @@ struct CodeGenerator { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_CodeGenerator_outputFormat_get(Int32(bitPattern: self.this.id)) + let ret = bjs_CodeGenerator_outputFormat_get(self.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } + return String.bridgeJSLiftReturn(ret) } } @@ -160,14 +131,11 @@ struct CodeGenerator { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_CodeGenerator_generate(Int32(bitPattern: self.this.id), Int32(bitPattern: input.id)) + let ret = bjs_CodeGenerator_generate(self.bridgeJSLowerParameter(), input.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } + return String.bridgeJSLiftReturn(ret) } } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TypeAlias.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TypeAlias.swift index 7523101f..d8b18463 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TypeAlias.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TypeAlias.swift @@ -15,7 +15,7 @@ func checkSimple(_ a: Double) throws(JSException) -> Void { fatalError("Only available on WebAssembly") } #endif - bjs_checkSimple(a) + bjs_checkSimple(a.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TypeScriptClass.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TypeScriptClass.swift index 7a1f2a2c..455b38bc 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TypeScriptClass.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TypeScriptClass.swift @@ -6,15 +6,11 @@ @_spi(BridgeJS) import JavaScriptKit -struct Greeter { - let this: JSObject +struct Greeter: _JSBridgedClass { + let jsObject: JSObject - init(this: JSObject) { - self.this = this - } - - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject } init(_ name: String) throws(JSException) { @@ -26,15 +22,11 @@ struct Greeter { fatalError("Only available on WebAssembly") } #endif - var name = name - let nameId = name.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_Greeter_init(nameId) + let ret = bjs_Greeter_init(name.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - self.this = JSObject(id: UInt32(bitPattern: ret)) + self.jsObject = JSObject(id: UInt32(bitPattern: ret)) } var name: String { @@ -47,14 +39,11 @@ struct Greeter { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_Greeter_name_get(Int32(bitPattern: self.this.id)) + let ret = bjs_Greeter_name_get(self.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } + return String.bridgeJSLiftReturn(ret) } } @@ -67,11 +56,7 @@ struct Greeter { fatalError("Only available on WebAssembly") } #endif - var newValue = newValue - let newValueId = newValue.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_Greeter_name_set(Int32(bitPattern: self.this.id), newValueId) + bjs_Greeter_name_set(self.bridgeJSLowerParameter(), newValue.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } @@ -87,11 +72,11 @@ struct Greeter { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_Greeter_age_get(Int32(bitPattern: self.this.id)) + let ret = bjs_Greeter_age_get(self.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return Double(ret) + return Double.bridgeJSLiftReturn(ret) } } @@ -104,14 +89,11 @@ struct Greeter { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_Greeter_greet(Int32(bitPattern: self.this.id)) + let ret = bjs_Greeter_greet(self.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } + return String.bridgeJSLiftReturn(ret) } func changeName(_ name: String) throws(JSException) -> Void { @@ -123,11 +105,7 @@ struct Greeter { fatalError("Only available on WebAssembly") } #endif - var name = name - let nameId = name.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_Greeter_changeName(Int32(bitPattern: self.this.id), nameId) + bjs_Greeter_changeName(self.bridgeJSLowerParameter(), name.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } diff --git a/Plugins/PackageToJS/Sources/BridgeJSUtilities b/Plugins/PackageToJS/Sources/BridgeJSUtilities new file mode 120000 index 00000000..52bf489d --- /dev/null +++ b/Plugins/PackageToJS/Sources/BridgeJSUtilities @@ -0,0 +1 @@ +../../../Plugins/BridgeJS/Sources/BridgeJSUtilities \ No newline at end of file diff --git a/Plugins/PackageToJS/Templates/instantiate.js b/Plugins/PackageToJS/Templates/instantiate.js index 5d6fe6b9..9b35efd1 100644 --- a/Plugins/PackageToJS/Templates/instantiate.js +++ b/Plugins/PackageToJS/Templates/instantiate.js @@ -27,7 +27,20 @@ async function createInstantiator(options, swift) { * @param {WebAssembly.Imports} importObject * @param {unknown} importsContext */ - addImports: (importObject, importsContext) => {}, + addImports: (importObject, importsContext) => { + // Provide a default implementation for BridgeJS functions that are not + // used at runtime without BridgeJS but required to instantiate the module. + const unexpectedBjsCall = () => { throw new Error("Unexpected call to BridgeJS function") } + importObject["bjs"] = { + swift_js_return_string: unexpectedBjsCall, + swift_js_init_memory: unexpectedBjsCall, + swift_js_make_js_string: unexpectedBjsCall, + swift_js_init_memory_with_result: unexpectedBjsCall, + swift_js_throw: unexpectedBjsCall, + swift_js_retain: unexpectedBjsCall, + swift_js_release: unexpectedBjsCall, + } + }, /** @param {WebAssembly.Instance} instance */ setInstance: (instance) => {}, /** @param {WebAssembly.Instance} instance */ diff --git a/Sources/BridgeJSTool/BridgeJSUtilities b/Sources/BridgeJSTool/BridgeJSUtilities new file mode 120000 index 00000000..75db3bd9 --- /dev/null +++ b/Sources/BridgeJSTool/BridgeJSUtilities @@ -0,0 +1 @@ +../../Plugins/BridgeJS/Sources/BridgeJSUtilities \ No newline at end of file diff --git a/Sources/JavaScriptKit/BasicObjects/JSPromise.swift b/Sources/JavaScriptKit/BasicObjects/JSPromise.swift index ec2a7724..201e8fa6 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSPromise.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSPromise.swift @@ -23,10 +23,6 @@ public final class JSPromise: JSBridgedClass { self.init(from: jsObject) } - @_spi(BridgeJS) public convenience init(takingThis: Int32) { - self.init(unsafelyWrapping: JSObject(id: UInt32(bitPattern: takingThis))) - } - /// Creates a new `JSPromise` instance from a given JavaScript `Promise` object. If `value` /// is not an object and is not an instance of JavaScript `Promise`, this function will /// return `nil`. diff --git a/Sources/JavaScriptKit/BridgeJSInstrincics.swift b/Sources/JavaScriptKit/BridgeJSInstrincics.swift index 1a8bad7f..56b87fa5 100644 --- a/Sources/JavaScriptKit/BridgeJSInstrincics.swift +++ b/Sources/JavaScriptKit/BridgeJSInstrincics.swift @@ -1,3 +1,8 @@ +/// BridgeJS Intrinsics +/// +/// This file contains low-level intrinsic functions that are used by code generated +/// by the BridgeJS system. + import _CJavaScriptKit #if !arch(wasm32) @@ -6,60 +11,31 @@ import _CJavaScriptKit } #endif -#if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_return_string") -@_spi(BridgeJS) public func _swift_js_return_string(_ ptr: UnsafePointer?, _ len: Int32) -#else -@_spi(BridgeJS) public func _swift_js_return_string(_ ptr: UnsafePointer?, _ len: Int32) { - _onlyAvailableOnWasm() -} -#endif - -#if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_init_memory") -@_spi(BridgeJS) public func _swift_js_init_memory(_ sourceId: Int32, _ ptr: UnsafeMutablePointer?) -#else -@_spi(BridgeJS) public func _swift_js_init_memory(_ sourceId: Int32, _ ptr: UnsafeMutablePointer?) { - _onlyAvailableOnWasm() -} -#endif - -#if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_retain") -@_spi(BridgeJS) public func _swift_js_retain(_ ptr: Int32) -> Int32 -#else -@_spi(BridgeJS) public func _swift_js_retain(_ ptr: Int32) -> Int32 { - _onlyAvailableOnWasm() -} -#endif +// MARK: Exception Handling #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_throw") @_spi(BridgeJS) public func _swift_js_throw(_ id: Int32) #else +/// Throws a JavaScript exception from Swift code. +/// +/// This function is called by the BridgeJS code generator when a Swift function throws +/// an error. The exception object is retained and stored for later retrieval by the +/// JavaScript-side runtime code. +/// +/// - Parameter id: The ID of the JavaScript exception object to throw @_spi(BridgeJS) public func _swift_js_throw(_ id: Int32) { _onlyAvailableOnWasm() } #endif -#if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_make_js_string") -@_spi(BridgeJS) public func _swift_js_make_js_string(_ ptr: UnsafePointer?, _ len: Int32) -> Int32 -#else -@_spi(BridgeJS) public func _swift_js_make_js_string(_ ptr: UnsafePointer?, _ len: Int32) -> Int32 { - _onlyAvailableOnWasm() -} -#endif - -#if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_init_memory_with_result") -@_spi(BridgeJS) public func _swift_js_init_memory_with_result(_ ptr: UnsafePointer?, _ len: Int32) -#else -@_spi(BridgeJS) public func _swift_js_init_memory_with_result(_ ptr: UnsafePointer?, _ len: Int32) { - _onlyAvailableOnWasm() -} -#endif - +/// Retrieves and clears any pending JavaScript exception. +/// +/// This function checks for any JavaScript exceptions that were thrown during +/// the execution of imported JavaScript functions. If an exception exists, it +/// is retrieved, cleared from the global storage, and returned as a `JSException`. +/// +/// - Returns: A `JSException` if an exception was pending, `nil` otherwise @_spi(BridgeJS) @_transparent public func _swift_js_take_exception() -> JSException? { #if arch(wasm32) let value = _swift_js_exception_get() @@ -72,3 +48,293 @@ import _CJavaScriptKit _onlyAvailableOnWasm() #endif } + +// MARK: Type lowering/lifting +// +// The following part defines the parameter and return value lowering/lifting +// for a given type. They follow the following pattern: +// +// ```swift +// extension <#TargetType#> { +// // MARK: ImportTS +// @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> <#WasmCoreType#> { +// } +// @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ ...) -> <#Self#> { +// } +// // MARK: ExportSwift +// @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ ...) -> <#Self#> { +// } +// @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> <#WasmCoreType#> { +// } +// } +// ``` +// +// where: +// - <#TargetType#>: the higher-level type to be lowered/lifted +// - <#WasmCoreType#>: the corresponding WebAssembly core type or Void +// - `func bridgeJSLowerParameter()`: lower the given higher-level parameter to a WebAssembly core type +// - `func bridgeJSLiftReturn(_ ...) -> <#TargetType#>`: lift the given Wasm core type return value to a higher-level type +// - `func bridgeJSLiftParameter(_ ...) -> <#TargetType#>`: lift the given Wasm core type parameters to a higher-level type +// - `func bridgeJSLowerReturn() -> <#WasmCoreType#>`: lower the given higher-level return value to a Wasm core type +// +// See JSGlueGen.swift in BridgeJSLink for JS-side lowering/lifting implementation. + +/// A protocol that Swift types that can appear as parameters or return values on +public protocol _BridgedSwiftTypeLoweredIntoSingleWasmCoreType { + associatedtype WasmCoreType + // MARK: ImportTS + consuming func bridgeJSLowerParameter() -> WasmCoreType + static func bridgeJSLiftReturn(_ value: WasmCoreType) -> Self + // MARK: ExportSwift + static func bridgeJSLiftParameter(_ value: WasmCoreType) -> Self + consuming func bridgeJSLowerReturn() -> WasmCoreType +} + +extension Bool: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType { + // MARK: ImportTS + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + self ? 1 : 0 + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Bool { + value == 1 + } + // MARK: ExportSwift + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Bool { + value == 1 + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + self ? 1 : 0 + } +} + +extension Int: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType { + // MARK: ImportTS + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + Int32(self) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Int { + Int(value) + } + // MARK: ExportSwift + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Int { + Int(value) + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + Int32(self) + } +} + +extension Float: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType { + // MARK: ImportTS + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Float32 { + Float32(self) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Float32) -> Float { + Float(value) + } + // MARK: ExportSwift + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Float32) -> Float { + Float(value) + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Float32 { + Float32(self) + } +} + +extension Double: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType { + // MARK: ImportTS + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Float64 { + Float64(self) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Float64) -> Double { + Double(value) + } + // MARK: ExportSwift + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Float64) -> Double { + Double(value) + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Float64 { + Float64(self) + } +} + +extension String { + // MARK: ImportTS + + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Int32 { + #if arch(wasm32) + @_extern(wasm, module: "bjs", name: "swift_js_make_js_string") + func _swift_js_make_js_string(_ ptr: UnsafePointer?, _ len: Int32) -> Int32 + #else + /// Creates a JavaScript string from UTF-8 data in WebAssembly memory + func _swift_js_make_js_string(_ ptr: UnsafePointer?, _ len: Int32) -> Int32 { + _onlyAvailableOnWasm() + } + #endif + return self.withUTF8 { b in + _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) + } + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ bytesCount: Int32) -> String { + #if arch(wasm32) + @_extern(wasm, module: "bjs", name: "swift_js_init_memory_with_result") + func _swift_js_init_memory_with_result(_ ptr: UnsafePointer?, _ len: Int32) + #else + /// Initializes WebAssembly memory with result data of JavaScript function call + func _swift_js_init_memory_with_result(_ ptr: UnsafePointer?, _ len: Int32) { + _onlyAvailableOnWasm() + } + guard #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) else { _onlyAvailableOnWasm() } + #endif + return String(unsafeUninitializedCapacity: Int(bytesCount)) { b in + _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(bytesCount)) + return Int(bytesCount) + } + } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ bytes: Int32, _ count: Int32) -> String { + #if arch(wasm32) + @_extern(wasm, module: "bjs", name: "swift_js_init_memory") + func _swift_js_init_memory(_ sourceId: Int32, _ ptr: UnsafeMutablePointer?) + #else + /// Initializes a part of WebAssembly memory with Uint8Array a JavaScript object + func _swift_js_init_memory(_ sourceId: Int32, _ ptr: UnsafeMutablePointer?) { + _onlyAvailableOnWasm() + } + guard #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) else { _onlyAvailableOnWasm() } + #endif + return String(unsafeUninitializedCapacity: Int(count)) { b in + _swift_js_init_memory(bytes, b.baseAddress.unsafelyUnwrapped) + return Int(count) + } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + #if arch(wasm32) + @_extern(wasm, module: "bjs", name: "swift_js_return_string") + func _swift_js_return_string(_ ptr: UnsafePointer?, _ len: Int32) + #else + /// Write a string to reserved string storage to be returned to JavaScript + func _swift_js_return_string(_ ptr: UnsafePointer?, _ len: Int32) { + _onlyAvailableOnWasm() + } + #endif + return self.withUTF8 { ptr in + _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) + } + } +} + +extension JSObject { + // MARK: ImportTS + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + Int32(bitPattern: self.id) + } + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ id: Int32) -> JSObject { + JSObject(id: JavaScriptObjectRef(bitPattern: id)) + } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ id: Int32) -> JSObject { + JSObject(id: JavaScriptObjectRef(bitPattern: id)) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Int32 { + #if arch(wasm32) + @_extern(wasm, module: "bjs", name: "swift_js_retain") + func _swift_js_retain(_ id: Int32) -> Int32 + #else + /// Retains a JavaScript object reference to ensure the object id + /// remains valid after the function returns + func _swift_js_retain(_ id: Int32) -> Int32 { + _onlyAvailableOnWasm() + } + #endif + return _swift_js_retain(Int32(bitPattern: self.id)) + } +} + +/// A protocol that Swift heap objects exposed to JavaScript via `@JS class` must conform to. +/// +/// The conformance is automatically synthesized by the BridgeJS code generator. +public protocol _BridgedSwiftHeapObject: AnyObject {} + +/// Define the lowering/lifting for `_BridgedSwiftHeapObject` +extension _BridgedSwiftHeapObject { + + // MARK: ImportTS + @available(*, unavailable, message: "Swift heap objects are not supported to be passed to imported JS functions") + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Void {} + @available( + *, + unavailable, + message: "Swift heap objects are not supported to be returned from imported JS functions" + ) + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ pointer: UnsafeMutableRawPointer) -> Void {} + + // MARK: ExportSwift + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ pointer: UnsafeMutableRawPointer) -> Self { + Unmanaged.fromOpaque(pointer).takeUnretainedValue() + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> UnsafeMutableRawPointer { + // Perform a manual retain on the object, which will be balanced by a release called via FinalizationRegistry + return Unmanaged.passRetained(self).toOpaque() + } +} + +extension _JSBridgedClass { + // MARK: ImportTS + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Int32 { jsObject.bridgeJSLowerParameter() } + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ id: Int32) -> Self { + Self(unsafelyWrapping: JSObject.bridgeJSLiftReturn(id)) + } + + // MARK: ExportSwift + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ id: Int32) -> Self { + Self(unsafelyWrapping: JSObject.bridgeJSLiftParameter(id)) + } + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Int32 { jsObject.bridgeJSLowerReturn() } +} + +/// A protocol that Swift enum types that do not have a payload can conform to. +/// +/// The conformance is automatically synthesized by the BridgeJS code generator. +public protocol _BridgedSwiftEnumNoPayload {} + +extension _BridgedSwiftEnumNoPayload where Self: RawRepresentable, RawValue == String { + // MARK: ImportTS + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Int32 { rawValue.bridgeJSLowerParameter() } + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ bytesCount: Int32) -> Self { + Self(rawValue: .bridgeJSLiftReturn(bytesCount))! + } + + // MARK: ExportSwift + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ bytes: Int32, _ count: Int32) -> Self { + Self(rawValue: .bridgeJSLiftParameter(bytes, count))! + } + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { rawValue.bridgeJSLowerReturn() } +} + +extension _BridgedSwiftEnumNoPayload +where Self: RawRepresentable, RawValue: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType { + // MARK: ImportTS + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> RawValue.WasmCoreType { + rawValue.bridgeJSLowerParameter() + } + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ value: RawValue.WasmCoreType) -> Self { + Self(rawValue: .bridgeJSLiftReturn(value))! + } + + // MARK: ExportSwift + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ value: RawValue.WasmCoreType) -> Self { + Self(rawValue: .bridgeJSLiftParameter(value))! + } + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> RawValue.WasmCoreType { + rawValue.bridgeJSLowerReturn() + } +} diff --git a/Sources/JavaScriptKit/JSBridgedType.swift b/Sources/JavaScriptKit/JSBridgedType.swift index 92739079..ffa65f4a 100644 --- a/Sources/JavaScriptKit/JSBridgedType.swift +++ b/Sources/JavaScriptKit/JSBridgedType.swift @@ -13,8 +13,21 @@ extension JSBridgedType { public var description: String { jsValue.description } } +/// A protocol that Swift classes that are exposed to JavaScript via `@JS class` conform to. +/// +/// The conformance is automatically synthesized by the BridgeJS code generator. +public protocol _JSBridgedClass { + /// The JavaScript object wrapped by this instance. + /// You may assume that `jsObject instanceof Self.constructor == true` + var jsObject: JSObject { get } + + /// Create an instance wrapping the given JavaScript object. + /// You may assume that `jsObject instanceof Self.constructor` + init(unsafelyWrapping jsObject: JSObject) +} + /// Conform to this protocol when your Swift class wraps a JavaScript class. -public protocol JSBridgedClass: JSBridgedType { +public protocol JSBridgedClass: JSBridgedType, _JSBridgedClass { /// The constructor function for the JavaScript class static var constructor: JSFunction? { get } diff --git a/Sources/_CJavaScriptKit/include/BridgeJSInstrincics.h b/Sources/_CJavaScriptKit/include/BridgeJSInstrincics.h index 4f5ba93c..7ca09860 100644 --- a/Sources/_CJavaScriptKit/include/BridgeJSInstrincics.h +++ b/Sources/_CJavaScriptKit/include/BridgeJSInstrincics.h @@ -5,6 +5,8 @@ #include "WasmGlobalMacros.h" #if __wasm__ +// Global thread-local pointer storage for temporarily storing JS exceptions +// thrown from imported JavaScript functions. WASM_GLOBAL_DEFINE_INLINE_ACCESSORS(_swift_js_exception, i32, int32_t) #endif diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift index d51f954e..e5999f4d 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift @@ -7,7 +7,20 @@ @_spi(BridgeJS) import JavaScriptKit extension Direction { - init?(bridgeJSRawValue: Int32) { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Direction { + return Direction(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Direction { + return Direction(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSRawValue + } + + private init?(bridgeJSRawValue: Int32) { switch bridgeJSRawValue { case 0: self = .north @@ -22,7 +35,7 @@ extension Direction { } } - var bridgeJSRawValue: Int32 { + private var bridgeJSRawValue: Int32 { switch self { case .north: return 0 @@ -37,7 +50,20 @@ extension Direction { } extension Status { - init?(bridgeJSRawValue: Int32) { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Status { + return Status(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Status { + return Status(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSRawValue + } + + private init?(bridgeJSRawValue: Int32) { switch bridgeJSRawValue { case 0: self = .loading @@ -50,7 +76,7 @@ extension Status { } } - var bridgeJSRawValue: Int32 { + private var bridgeJSRawValue: Int32 { switch self { case .loading: return 0 @@ -62,8 +88,27 @@ extension Status { } } +extension Theme: _BridgedSwiftEnumNoPayload { +} + +extension HttpStatus: _BridgedSwiftEnumNoPayload { +} + extension TSDirection { - init?(bridgeJSRawValue: Int32) { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> TSDirection { + return TSDirection(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> TSDirection { + return TSDirection(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSRawValue + } + + private init?(bridgeJSRawValue: Int32) { switch bridgeJSRawValue { case 0: self = .north @@ -78,7 +123,7 @@ extension TSDirection { } } - var bridgeJSRawValue: Int32 { + private var bridgeJSRawValue: Int32 { switch self { case .north: return 0 @@ -92,8 +137,27 @@ extension TSDirection { } } +extension TSTheme: _BridgedSwiftEnumNoPayload { +} + +extension Utils: _BridgedSwiftEnumNoPayload { +} + extension Networking.API.Method { - init?(bridgeJSRawValue: Int32) { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Networking.API.Method { + return Networking.API.Method(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Networking.API.Method { + return Networking.API.Method(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSRawValue + } + + private init?(bridgeJSRawValue: Int32) { switch bridgeJSRawValue { case 0: self = .get @@ -108,7 +172,7 @@ extension Networking.API.Method { } } - var bridgeJSRawValue: Int32 { + private var bridgeJSRawValue: Int32 { switch self { case .get: return 0 @@ -122,8 +186,27 @@ extension Networking.API.Method { } } +extension Configuration.LogLevel: _BridgedSwiftEnumNoPayload { +} + +extension Configuration.Port: _BridgedSwiftEnumNoPayload { +} + extension Internal.SupportedMethod { - init?(bridgeJSRawValue: Int32) { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Internal.SupportedMethod { + return Internal.SupportedMethod(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Internal.SupportedMethod { + return Internal.SupportedMethod(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSRawValue + } + + private init?(bridgeJSRawValue: Int32) { switch bridgeJSRawValue { case 0: self = .get @@ -134,7 +217,7 @@ extension Internal.SupportedMethod { } } - var bridgeJSRawValue: Int32 { + private var bridgeJSRawValue: Int32 { switch self { case .get: return 0 @@ -158,8 +241,8 @@ public func _bjs_roundTripVoid() -> Void { @_cdecl("bjs_roundTripInt") public func _bjs_roundTripInt(v: Int32) -> Int32 { #if arch(wasm32) - let ret = roundTripInt(v: Int(v)) - return Int32(ret) + let ret = roundTripInt(v: Int.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -169,8 +252,8 @@ public func _bjs_roundTripInt(v: Int32) -> Int32 { @_cdecl("bjs_roundTripFloat") public func _bjs_roundTripFloat(v: Float32) -> Float32 { #if arch(wasm32) - let ret = roundTripFloat(v: v) - return Float32(ret) + let ret = roundTripFloat(v: Float.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -180,8 +263,8 @@ public func _bjs_roundTripFloat(v: Float32) -> Float32 { @_cdecl("bjs_roundTripDouble") public func _bjs_roundTripDouble(v: Float64) -> Float64 { #if arch(wasm32) - let ret = roundTripDouble(v: v) - return Float64(ret) + let ret = roundTripDouble(v: Double.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -191,8 +274,8 @@ public func _bjs_roundTripDouble(v: Float64) -> Float64 { @_cdecl("bjs_roundTripBool") public func _bjs_roundTripBool(v: Int32) -> Int32 { #if arch(wasm32) - let ret = roundTripBool(v: v == 1) - return Int32(ret ? 1 : 0) + let ret = roundTripBool(v: Bool.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -200,16 +283,10 @@ public func _bjs_roundTripBool(v: Int32) -> Int32 { @_expose(wasm, "bjs_roundTripString") @_cdecl("bjs_roundTripString") -public func _bjs_roundTripString(vBytes: Int32, vLen: Int32) -> Void { +public func _bjs_roundTripString(vBytes: Int32, vLength: Int32) -> Void { #if arch(wasm32) - let v = String(unsafeUninitializedCapacity: Int(vLen)) { b in - _swift_js_init_memory(vBytes, b.baseAddress.unsafelyUnwrapped) - return Int(vLen) - } - var ret = roundTripString(v: v) - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = roundTripString(v: String.bridgeJSLiftParameter(vBytes, vLength)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -219,8 +296,8 @@ public func _bjs_roundTripString(vBytes: Int32, vLen: Int32) -> Void { @_cdecl("bjs_roundTripSwiftHeapObject") public func _bjs_roundTripSwiftHeapObject(v: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { #if arch(wasm32) - let ret = roundTripSwiftHeapObject(v: Unmanaged.fromOpaque(v).takeUnretainedValue()) - return Unmanaged.passRetained(ret).toOpaque() + let ret = roundTripSwiftHeapObject(v: Greeter.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -230,8 +307,8 @@ public func _bjs_roundTripSwiftHeapObject(v: UnsafeMutableRawPointer) -> UnsafeM @_cdecl("bjs_roundTripJSObject") public func _bjs_roundTripJSObject(v: Int32) -> Int32 { #if arch(wasm32) - let ret = roundTripJSObject(v: JSObject(id: UInt32(bitPattern: v))) - return _swift_js_retain(Int32(bitPattern: ret.id)) + let ret = roundTripJSObject(v: JSObject.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -242,7 +319,7 @@ public func _bjs_roundTripJSObject(v: Int32) -> Int32 { public func _bjs_throwsSwiftError(shouldThrow: Int32) -> Void { #if arch(wasm32) do { - try throwsSwiftError(shouldThrow: shouldThrow == 1) + try throwsSwiftError(shouldThrow: Bool.bridgeJSLiftParameter(shouldThrow)) } catch let error { if let error = error.thrownValue.object { withExtendedLifetime(error) { @@ -267,7 +344,7 @@ public func _bjs_throwsWithIntResult() -> Int32 { #if arch(wasm32) do { let ret = try throwsWithIntResult() - return Int32(ret) + return ret.bridgeJSLowerReturn() } catch let error { if let error = error.thrownValue.object { withExtendedLifetime(error) { @@ -291,10 +368,8 @@ public func _bjs_throwsWithIntResult() -> Int32 { public func _bjs_throwsWithStringResult() -> Void { #if arch(wasm32) do { - var ret = try throwsWithStringResult() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = try throwsWithStringResult() + return ret.bridgeJSLowerReturn() } catch let error { if let error = error.thrownValue.object { withExtendedLifetime(error) { @@ -319,7 +394,7 @@ public func _bjs_throwsWithBoolResult() -> Int32 { #if arch(wasm32) do { let ret = try throwsWithBoolResult() - return Int32(ret ? 1 : 0) + return ret.bridgeJSLowerReturn() } catch let error { if let error = error.thrownValue.object { withExtendedLifetime(error) { @@ -344,7 +419,7 @@ public func _bjs_throwsWithFloatResult() -> Float32 { #if arch(wasm32) do { let ret = try throwsWithFloatResult() - return Float32(ret) + return ret.bridgeJSLowerReturn() } catch let error { if let error = error.thrownValue.object { withExtendedLifetime(error) { @@ -369,7 +444,7 @@ public func _bjs_throwsWithDoubleResult() -> Float64 { #if arch(wasm32) do { let ret = try throwsWithDoubleResult() - return Float64(ret) + return ret.bridgeJSLowerReturn() } catch let error { if let error = error.thrownValue.object { withExtendedLifetime(error) { @@ -394,7 +469,7 @@ public func _bjs_throwsWithSwiftHeapObjectResult() -> UnsafeMutableRawPointer { #if arch(wasm32) do { let ret = try throwsWithSwiftHeapObjectResult() - return Unmanaged.passRetained(ret).toOpaque() + return ret.bridgeJSLowerReturn() } catch let error { if let error = error.thrownValue.object { withExtendedLifetime(error) { @@ -419,7 +494,7 @@ public func _bjs_throwsWithJSObjectResult() -> Int32 { #if arch(wasm32) do { let ret = try throwsWithJSObjectResult() - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() } catch let error { if let error = error.thrownValue.object { withExtendedLifetime(error) { @@ -445,7 +520,7 @@ public func _bjs_asyncRoundTripVoid() -> Int32 { let ret = JSPromise.async { await asyncRoundTripVoid() } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -456,9 +531,9 @@ public func _bjs_asyncRoundTripVoid() -> Int32 { public func _bjs_asyncRoundTripInt(v: Int32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { - return await asyncRoundTripInt(v: Int(v)).jsValue + return await asyncRoundTripInt(v: Int.bridgeJSLiftParameter(v)).jsValue } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -469,9 +544,9 @@ public func _bjs_asyncRoundTripInt(v: Int32) -> Int32 { public func _bjs_asyncRoundTripFloat(v: Float32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { - return await asyncRoundTripFloat(v: v).jsValue + return await asyncRoundTripFloat(v: Float.bridgeJSLiftParameter(v)).jsValue } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -482,9 +557,9 @@ public func _bjs_asyncRoundTripFloat(v: Float32) -> Int32 { public func _bjs_asyncRoundTripDouble(v: Float64) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { - return await asyncRoundTripDouble(v: v).jsValue + return await asyncRoundTripDouble(v: Double.bridgeJSLiftParameter(v)).jsValue } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -495,9 +570,9 @@ public func _bjs_asyncRoundTripDouble(v: Float64) -> Int32 { public func _bjs_asyncRoundTripBool(v: Int32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { - return await asyncRoundTripBool(v: v == 1).jsValue + return await asyncRoundTripBool(v: Bool.bridgeJSLiftParameter(v)).jsValue } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -505,16 +580,12 @@ public func _bjs_asyncRoundTripBool(v: Int32) -> Int32 { @_expose(wasm, "bjs_asyncRoundTripString") @_cdecl("bjs_asyncRoundTripString") -public func _bjs_asyncRoundTripString(vBytes: Int32, vLen: Int32) -> Int32 { +public func _bjs_asyncRoundTripString(vBytes: Int32, vLength: Int32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { - let v = String(unsafeUninitializedCapacity: Int(vLen)) { b in - _swift_js_init_memory(vBytes, b.baseAddress.unsafelyUnwrapped) - return Int(vLen) - } - return await asyncRoundTripString(v: v).jsValue + return await asyncRoundTripString(v: String.bridgeJSLiftParameter(vBytes, vLength)).jsValue } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -525,9 +596,9 @@ public func _bjs_asyncRoundTripString(vBytes: Int32, vLen: Int32) -> Int32 { public func _bjs_asyncRoundTripSwiftHeapObject(v: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { - return await asyncRoundTripSwiftHeapObject(v: Unmanaged.fromOpaque(v).takeUnretainedValue()).jsValue + return await asyncRoundTripSwiftHeapObject(v: Greeter.bridgeJSLiftParameter(v)).jsValue } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -538,9 +609,9 @@ public func _bjs_asyncRoundTripSwiftHeapObject(v: UnsafeMutableRawPointer) -> In public func _bjs_asyncRoundTripJSObject(v: Int32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { - return await asyncRoundTripJSObject(v: JSObject(id: UInt32(bitPattern: v))).jsValue + return await asyncRoundTripJSObject(v: JSObject.bridgeJSLiftParameter(v)).jsValue } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -548,13 +619,9 @@ public func _bjs_asyncRoundTripJSObject(v: Int32) -> Int32 { @_expose(wasm, "bjs_takeGreeter") @_cdecl("bjs_takeGreeter") -public func _bjs_takeGreeter(g: UnsafeMutableRawPointer, nameBytes: Int32, nameLen: Int32) -> Void { +public func _bjs_takeGreeter(g: UnsafeMutableRawPointer, nameBytes: Int32, nameLength: Int32) -> Void { #if arch(wasm32) - let name = String(unsafeUninitializedCapacity: Int(nameLen)) { b in - _swift_js_init_memory(nameBytes, b.baseAddress.unsafelyUnwrapped) - return Int(nameLen) - } - takeGreeter(g: Unmanaged.fromOpaque(g).takeUnretainedValue(), name: name) + takeGreeter(g: Greeter.bridgeJSLiftParameter(g), name: String.bridgeJSLiftParameter(nameBytes, nameLength)) #else fatalError("Only available on WebAssembly") #endif @@ -565,7 +632,7 @@ public func _bjs_takeGreeter(g: UnsafeMutableRawPointer, nameBytes: Int32, nameL public func _bjs_createCalculator() -> UnsafeMutableRawPointer { #if arch(wasm32) let ret = createCalculator() - return Unmanaged.passRetained(ret).toOpaque() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -575,8 +642,8 @@ public func _bjs_createCalculator() -> UnsafeMutableRawPointer { @_cdecl("bjs_useCalculator") public func _bjs_useCalculator(calc: UnsafeMutableRawPointer, x: Int32, y: Int32) -> Int32 { #if arch(wasm32) - let ret = useCalculator(calc: Unmanaged.fromOpaque(calc).takeUnretainedValue(), x: Int(x), y: Int(y)) - return Int32(ret) + let ret = useCalculator(calc: Calculator.bridgeJSLiftParameter(calc), x: Int.bridgeJSLiftParameter(x), y: Int.bridgeJSLiftParameter(y)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -587,7 +654,7 @@ public func _bjs_useCalculator(calc: UnsafeMutableRawPointer, x: Int32, y: Int32 public func _bjs_testGreeterToJSValue() -> Int32 { #if arch(wasm32) let ret = testGreeterToJSValue() - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -598,7 +665,7 @@ public func _bjs_testGreeterToJSValue() -> Int32 { public func _bjs_testCalculatorToJSValue() -> Int32 { #if arch(wasm32) let ret = testCalculatorToJSValue() - return _swift_js_retain(Int32(bitPattern: ret.id)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -608,8 +675,8 @@ public func _bjs_testCalculatorToJSValue() -> Int32 { @_cdecl("bjs_testSwiftClassAsJSValue") public func _bjs_testSwiftClassAsJSValue(greeter: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = testSwiftClassAsJSValue(greeter: Unmanaged.fromOpaque(greeter).takeUnretainedValue()) - return _swift_js_retain(Int32(bitPattern: ret.id)) + let ret = testSwiftClassAsJSValue(greeter: Greeter.bridgeJSLiftParameter(greeter)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -619,8 +686,8 @@ public func _bjs_testSwiftClassAsJSValue(greeter: UnsafeMutableRawPointer) -> In @_cdecl("bjs_setDirection") public func _bjs_setDirection(direction: Int32) -> Int32 { #if arch(wasm32) - let ret = setDirection(_: Direction(bridgeJSRawValue: direction)!) - return ret.bridgeJSRawValue + let ret = setDirection(_: Direction.bridgeJSLiftParameter(direction)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -631,7 +698,7 @@ public func _bjs_setDirection(direction: Int32) -> Int32 { public func _bjs_getDirection() -> Int32 { #if arch(wasm32) let ret = getDirection() - return ret.bridgeJSRawValue + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -641,8 +708,8 @@ public func _bjs_getDirection() -> Int32 { @_cdecl("bjs_processDirection") public func _bjs_processDirection(input: Int32) -> Int32 { #if arch(wasm32) - let ret = processDirection(_: Direction(bridgeJSRawValue: input)!) - return ret.bridgeJSRawValue + let ret = processDirection(_: Direction.bridgeJSLiftParameter(input)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -650,17 +717,10 @@ public func _bjs_processDirection(input: Int32) -> Int32 { @_expose(wasm, "bjs_setTheme") @_cdecl("bjs_setTheme") -public func _bjs_setTheme(themeBytes: Int32, themeLen: Int32) -> Void { +public func _bjs_setTheme(themeBytes: Int32, themeLength: Int32) -> Void { #if arch(wasm32) - let theme = String(unsafeUninitializedCapacity: Int(themeLen)) { b in - _swift_js_init_memory(themeBytes, b.baseAddress.unsafelyUnwrapped) - return Int(themeLen) - } - let ret = setTheme(_: Theme(rawValue: theme)!) - var rawValue = ret.rawValue - return rawValue.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = setTheme(_: Theme.bridgeJSLiftParameter(themeBytes, themeLength)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -671,10 +731,7 @@ public func _bjs_setTheme(themeBytes: Int32, themeLen: Int32) -> Void { public func _bjs_getTheme() -> Void { #if arch(wasm32) let ret = getTheme() - var rawValue = ret.rawValue - return rawValue.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -684,8 +741,8 @@ public func _bjs_getTheme() -> Void { @_cdecl("bjs_setHttpStatus") public func _bjs_setHttpStatus(status: Int32) -> Int32 { #if arch(wasm32) - let ret = setHttpStatus(_: HttpStatus(rawValue: Int(status))!) - return Int32(ret.rawValue) + let ret = setHttpStatus(_: HttpStatus.bridgeJSLiftParameter(status)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -696,7 +753,7 @@ public func _bjs_setHttpStatus(status: Int32) -> Int32 { public func _bjs_getHttpStatus() -> Int32 { #if arch(wasm32) let ret = getHttpStatus() - return Int32(ret.rawValue) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -704,14 +761,10 @@ public func _bjs_getHttpStatus() -> Int32 { @_expose(wasm, "bjs_processTheme") @_cdecl("bjs_processTheme") -public func _bjs_processTheme(themeBytes: Int32, themeLen: Int32) -> Int32 { +public func _bjs_processTheme(themeBytes: Int32, themeLength: Int32) -> Int32 { #if arch(wasm32) - let theme = String(unsafeUninitializedCapacity: Int(themeLen)) { b in - _swift_js_init_memory(themeBytes, b.baseAddress.unsafelyUnwrapped) - return Int(themeLen) - } - let ret = processTheme(_: Theme(rawValue: theme)!) - return Int32(ret.rawValue) + let ret = processTheme(_: Theme.bridgeJSLiftParameter(themeBytes, themeLength)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -721,8 +774,8 @@ public func _bjs_processTheme(themeBytes: Int32, themeLen: Int32) -> Int32 { @_cdecl("bjs_setTSDirection") public func _bjs_setTSDirection(direction: Int32) -> Int32 { #if arch(wasm32) - let ret = setTSDirection(_: TSDirection(bridgeJSRawValue: direction)!) - return ret.bridgeJSRawValue + let ret = setTSDirection(_: TSDirection.bridgeJSLiftParameter(direction)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -733,7 +786,7 @@ public func _bjs_setTSDirection(direction: Int32) -> Int32 { public func _bjs_getTSDirection() -> Int32 { #if arch(wasm32) let ret = getTSDirection() - return ret.bridgeJSRawValue + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -741,17 +794,10 @@ public func _bjs_getTSDirection() -> Int32 { @_expose(wasm, "bjs_setTSTheme") @_cdecl("bjs_setTSTheme") -public func _bjs_setTSTheme(themeBytes: Int32, themeLen: Int32) -> Void { +public func _bjs_setTSTheme(themeBytes: Int32, themeLength: Int32) -> Void { #if arch(wasm32) - let theme = String(unsafeUninitializedCapacity: Int(themeLen)) { b in - _swift_js_init_memory(themeBytes, b.baseAddress.unsafelyUnwrapped) - return Int(themeLen) - } - let ret = setTSTheme(_: TSTheme(rawValue: theme)!) - var rawValue = ret.rawValue - return rawValue.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = setTSTheme(_: TSTheme.bridgeJSLiftParameter(themeBytes, themeLength)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -762,10 +808,7 @@ public func _bjs_setTSTheme(themeBytes: Int32, themeLen: Int32) -> Void { public func _bjs_getTSTheme() -> Void { #if arch(wasm32) let ret = getTSTheme() - var rawValue = ret.rawValue - return rawValue.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -773,14 +816,10 @@ public func _bjs_getTSTheme() -> Void { @_expose(wasm, "bjs_createPropertyHolder") @_cdecl("bjs_createPropertyHolder") -public func _bjs_createPropertyHolder(intValue: Int32, floatValue: Float32, doubleValue: Float64, boolValue: Int32, stringValueBytes: Int32, stringValueLen: Int32, jsObject: Int32) -> UnsafeMutableRawPointer { +public func _bjs_createPropertyHolder(intValue: Int32, floatValue: Float32, doubleValue: Float64, boolValue: Int32, stringValueBytes: Int32, stringValueLength: Int32, jsObject: Int32) -> UnsafeMutableRawPointer { #if arch(wasm32) - let stringValue = String(unsafeUninitializedCapacity: Int(stringValueLen)) { b in - _swift_js_init_memory(stringValueBytes, b.baseAddress.unsafelyUnwrapped) - return Int(stringValueLen) - } - let ret = createPropertyHolder(intValue: Int(intValue), floatValue: floatValue, doubleValue: doubleValue, boolValue: boolValue == 1, stringValue: stringValue, jsObject: JSObject(id: UInt32(bitPattern: jsObject))) - return Unmanaged.passRetained(ret).toOpaque() + let ret = createPropertyHolder(intValue: Int.bridgeJSLiftParameter(intValue), floatValue: Float.bridgeJSLiftParameter(floatValue), doubleValue: Double.bridgeJSLiftParameter(doubleValue), boolValue: Bool.bridgeJSLiftParameter(boolValue), stringValue: String.bridgeJSLiftParameter(stringValueBytes, stringValueLength), jsObject: JSObject.bridgeJSLiftParameter(jsObject)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -790,10 +829,8 @@ public func _bjs_createPropertyHolder(intValue: Int32, floatValue: Float32, doub @_cdecl("bjs_testPropertyHolder") public func _bjs_testPropertyHolder(holder: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = testPropertyHolder(holder: Unmanaged.fromOpaque(holder).takeUnretainedValue()) - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = testPropertyHolder(holder: PropertyHolder.bridgeJSLiftParameter(holder)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -813,10 +850,8 @@ public func _bjs_resetObserverCounts() -> Void { @_cdecl("bjs_getObserverStats") public func _bjs_getObserverStats() -> Void { #if arch(wasm32) - var ret = getObserverStats() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = getObserverStats() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -824,14 +859,10 @@ public func _bjs_getObserverStats() -> Void { @_expose(wasm, "bjs_Greeter_init") @_cdecl("bjs_Greeter_init") -public func _bjs_Greeter_init(nameBytes: Int32, nameLen: Int32) -> UnsafeMutableRawPointer { +public func _bjs_Greeter_init(nameBytes: Int32, nameLength: Int32) -> UnsafeMutableRawPointer { #if arch(wasm32) - let name = String(unsafeUninitializedCapacity: Int(nameLen)) { b in - _swift_js_init_memory(nameBytes, b.baseAddress.unsafelyUnwrapped) - return Int(nameLen) - } - let ret = Greeter(name: name) - return Unmanaged.passRetained(ret).toOpaque() + let ret = Greeter(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -841,10 +872,8 @@ public func _bjs_Greeter_init(nameBytes: Int32, nameLen: Int32) -> UnsafeMutable @_cdecl("bjs_Greeter_greet") public func _bjs_Greeter_greet(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().greet() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = Greeter.bridgeJSLiftParameter(_self).greet() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -852,13 +881,9 @@ public func _bjs_Greeter_greet(_self: UnsafeMutableRawPointer) -> Void { @_expose(wasm, "bjs_Greeter_changeName") @_cdecl("bjs_Greeter_changeName") -public func _bjs_Greeter_changeName(_self: UnsafeMutableRawPointer, nameBytes: Int32, nameLen: Int32) -> Void { +public func _bjs_Greeter_changeName(_self: UnsafeMutableRawPointer, nameBytes: Int32, nameLength: Int32) -> Void { #if arch(wasm32) - let name = String(unsafeUninitializedCapacity: Int(nameLen)) { b in - _swift_js_init_memory(nameBytes, b.baseAddress.unsafelyUnwrapped) - return Int(nameLen) - } - Unmanaged.fromOpaque(_self).takeUnretainedValue().changeName(name: name) + Greeter.bridgeJSLiftParameter(_self).changeName(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) #else fatalError("Only available on WebAssembly") #endif @@ -868,10 +893,8 @@ public func _bjs_Greeter_changeName(_self: UnsafeMutableRawPointer, nameBytes: I @_cdecl("bjs_Greeter_name_get") public func _bjs_Greeter_name_get(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().name - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = Greeter.bridgeJSLiftParameter(_self).name + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -879,13 +902,9 @@ public func _bjs_Greeter_name_get(_self: UnsafeMutableRawPointer) -> Void { @_expose(wasm, "bjs_Greeter_name_set") @_cdecl("bjs_Greeter_name_set") -public func _bjs_Greeter_name_set(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLen: Int32) -> Void { +public func _bjs_Greeter_name_set(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLength: Int32) -> Void { #if arch(wasm32) - let value = String(unsafeUninitializedCapacity: Int(valueLen)) { b in - _swift_js_init_memory(valueBytes, b.baseAddress.unsafelyUnwrapped) - return Int(valueLen) - } - Unmanaged.fromOpaque(_self).takeUnretainedValue().name = value + Greeter.bridgeJSLiftParameter(_self).name = String.bridgeJSLiftParameter(valueBytes, valueLength) #else fatalError("Only available on WebAssembly") #endif @@ -895,10 +914,8 @@ public func _bjs_Greeter_name_set(_self: UnsafeMutableRawPointer, valueBytes: In @_cdecl("bjs_Greeter_prefix_get") public func _bjs_Greeter_prefix_get(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().prefix - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = Greeter.bridgeJSLiftParameter(_self).prefix + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -910,10 +927,16 @@ public func _bjs_Greeter_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension Greeter: ConvertibleToJSValue { +extension Greeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Greeter_wrap") func _bjs_Greeter_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_Greeter_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_Greeter_wrap(Unmanaged.passRetained(self).toOpaque())))) } } @@ -922,8 +945,8 @@ extension Greeter: ConvertibleToJSValue { @_cdecl("bjs_Calculator_square") public func _bjs_Calculator_square(_self: UnsafeMutableRawPointer, value: Int32) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().square(value: Int(value)) - return Int32(ret) + let ret = Calculator.bridgeJSLiftParameter(_self).square(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -933,8 +956,8 @@ public func _bjs_Calculator_square(_self: UnsafeMutableRawPointer, value: Int32) @_cdecl("bjs_Calculator_add") public func _bjs_Calculator_add(_self: UnsafeMutableRawPointer, a: Int32, b: Int32) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().add(a: Int(a), b: Int(b)) - return Int32(ret) + let ret = Calculator.bridgeJSLiftParameter(_self).add(a: Int.bridgeJSLiftParameter(a), b: Int.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -946,10 +969,16 @@ public func _bjs_Calculator_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension Calculator: ConvertibleToJSValue { +extension Calculator: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Calculator_wrap") func _bjs_Calculator_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_Calculator_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_Calculator_wrap(Unmanaged.passRetained(self).toOpaque())))) } } @@ -959,7 +988,7 @@ extension Calculator: ConvertibleToJSValue { public func _bjs_Converter_init() -> UnsafeMutableRawPointer { #if arch(wasm32) let ret = Utils.Converter() - return Unmanaged.passRetained(ret).toOpaque() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -969,10 +998,8 @@ public func _bjs_Converter_init() -> UnsafeMutableRawPointer { @_cdecl("bjs_Converter_toString") public func _bjs_Converter_toString(_self: UnsafeMutableRawPointer, value: Int32) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().toString(value: Int(value)) - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = Utils.Converter.bridgeJSLiftParameter(_self).toString(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -984,10 +1011,16 @@ public func _bjs_Converter_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension Utils.Converter: ConvertibleToJSValue { +extension Utils.Converter: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Converter_wrap") func _bjs_Converter_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_Converter_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_Converter_wrap(Unmanaged.passRetained(self).toOpaque())))) } } @@ -997,7 +1030,7 @@ extension Utils.Converter: ConvertibleToJSValue { public func _bjs_HTTPServer_init() -> UnsafeMutableRawPointer { #if arch(wasm32) let ret = Networking.API.HTTPServer() - return Unmanaged.passRetained(ret).toOpaque() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1007,7 +1040,7 @@ public func _bjs_HTTPServer_init() -> UnsafeMutableRawPointer { @_cdecl("bjs_HTTPServer_call") public func _bjs_HTTPServer_call(_self: UnsafeMutableRawPointer, method: Int32) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().call(_: Networking.API.Method(bridgeJSRawValue: method)!) + Networking.API.HTTPServer.bridgeJSLiftParameter(_self).call(_: Networking.API.Method.bridgeJSLiftParameter(method)) #else fatalError("Only available on WebAssembly") #endif @@ -1019,10 +1052,16 @@ public func _bjs_HTTPServer_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension Networking.API.HTTPServer: ConvertibleToJSValue { +extension Networking.API.HTTPServer: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_HTTPServer_wrap") func _bjs_HTTPServer_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_HTTPServer_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_HTTPServer_wrap(Unmanaged.passRetained(self).toOpaque())))) } } @@ -1032,7 +1071,7 @@ extension Networking.API.HTTPServer: ConvertibleToJSValue { public func _bjs_TestServer_init() -> UnsafeMutableRawPointer { #if arch(wasm32) let ret = Internal.TestServer() - return Unmanaged.passRetained(ret).toOpaque() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1042,7 +1081,7 @@ public func _bjs_TestServer_init() -> UnsafeMutableRawPointer { @_cdecl("bjs_TestServer_call") public func _bjs_TestServer_call(_self: UnsafeMutableRawPointer, method: Int32) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().call(_: Internal.SupportedMethod(bridgeJSRawValue: method)!) + Internal.TestServer.bridgeJSLiftParameter(_self).call(_: Internal.SupportedMethod.bridgeJSLiftParameter(method)) #else fatalError("Only available on WebAssembly") #endif @@ -1054,10 +1093,16 @@ public func _bjs_TestServer_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension Internal.TestServer: ConvertibleToJSValue { +extension Internal.TestServer: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_TestServer_wrap") func _bjs_TestServer_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_TestServer_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_TestServer_wrap(Unmanaged.passRetained(self).toOpaque())))) } } @@ -1066,8 +1111,8 @@ extension Internal.TestServer: ConvertibleToJSValue { @_cdecl("bjs_SimplePropertyHolder_init") public func _bjs_SimplePropertyHolder_init(value: Int32) -> UnsafeMutableRawPointer { #if arch(wasm32) - let ret = SimplePropertyHolder(value: Int(value)) - return Unmanaged.passRetained(ret).toOpaque() + let ret = SimplePropertyHolder(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1077,8 +1122,8 @@ public func _bjs_SimplePropertyHolder_init(value: Int32) -> UnsafeMutableRawPoin @_cdecl("bjs_SimplePropertyHolder_value_get") public func _bjs_SimplePropertyHolder_value_get(_self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().value - return Int32(ret) + let ret = SimplePropertyHolder.bridgeJSLiftParameter(_self).value + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1088,7 +1133,7 @@ public func _bjs_SimplePropertyHolder_value_get(_self: UnsafeMutableRawPointer) @_cdecl("bjs_SimplePropertyHolder_value_set") public func _bjs_SimplePropertyHolder_value_set(_self: UnsafeMutableRawPointer, value: Int32) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().value = Int(value) + SimplePropertyHolder.bridgeJSLiftParameter(_self).value = Int.bridgeJSLiftParameter(value) #else fatalError("Only available on WebAssembly") #endif @@ -1100,24 +1145,26 @@ public func _bjs_SimplePropertyHolder_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension SimplePropertyHolder: ConvertibleToJSValue { +extension SimplePropertyHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_SimplePropertyHolder_wrap") func _bjs_SimplePropertyHolder_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_SimplePropertyHolder_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_SimplePropertyHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) } } @_expose(wasm, "bjs_PropertyHolder_init") @_cdecl("bjs_PropertyHolder_init") -public func _bjs_PropertyHolder_init(intValue: Int32, floatValue: Float32, doubleValue: Float64, boolValue: Int32, stringValueBytes: Int32, stringValueLen: Int32, jsObject: Int32, sibling: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +public func _bjs_PropertyHolder_init(intValue: Int32, floatValue: Float32, doubleValue: Float64, boolValue: Int32, stringValueBytes: Int32, stringValueLength: Int32, jsObject: Int32, sibling: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { #if arch(wasm32) - let stringValue = String(unsafeUninitializedCapacity: Int(stringValueLen)) { b in - _swift_js_init_memory(stringValueBytes, b.baseAddress.unsafelyUnwrapped) - return Int(stringValueLen) - } - let ret = PropertyHolder(intValue: Int(intValue), floatValue: floatValue, doubleValue: doubleValue, boolValue: boolValue == 1, stringValue: stringValue, jsObject: JSObject(id: UInt32(bitPattern: jsObject)), sibling: Unmanaged.fromOpaque(sibling).takeUnretainedValue()) - return Unmanaged.passRetained(ret).toOpaque() + let ret = PropertyHolder(intValue: Int.bridgeJSLiftParameter(intValue), floatValue: Float.bridgeJSLiftParameter(floatValue), doubleValue: Double.bridgeJSLiftParameter(doubleValue), boolValue: Bool.bridgeJSLiftParameter(boolValue), stringValue: String.bridgeJSLiftParameter(stringValueBytes, stringValueLength), jsObject: JSObject.bridgeJSLiftParameter(jsObject), sibling: SimplePropertyHolder.bridgeJSLiftParameter(sibling)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1127,10 +1174,8 @@ public func _bjs_PropertyHolder_init(intValue: Int32, floatValue: Float32, doubl @_cdecl("bjs_PropertyHolder_getAllValues") public func _bjs_PropertyHolder_getAllValues(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().getAllValues() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = PropertyHolder.bridgeJSLiftParameter(_self).getAllValues() + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1140,8 +1185,8 @@ public func _bjs_PropertyHolder_getAllValues(_self: UnsafeMutableRawPointer) -> @_cdecl("bjs_PropertyHolder_intValue_get") public func _bjs_PropertyHolder_intValue_get(_self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().intValue - return Int32(ret) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).intValue + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1151,7 +1196,7 @@ public func _bjs_PropertyHolder_intValue_get(_self: UnsafeMutableRawPointer) -> @_cdecl("bjs_PropertyHolder_intValue_set") public func _bjs_PropertyHolder_intValue_set(_self: UnsafeMutableRawPointer, value: Int32) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().intValue = Int(value) + PropertyHolder.bridgeJSLiftParameter(_self).intValue = Int.bridgeJSLiftParameter(value) #else fatalError("Only available on WebAssembly") #endif @@ -1161,8 +1206,8 @@ public func _bjs_PropertyHolder_intValue_set(_self: UnsafeMutableRawPointer, val @_cdecl("bjs_PropertyHolder_floatValue_get") public func _bjs_PropertyHolder_floatValue_get(_self: UnsafeMutableRawPointer) -> Float32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().floatValue - return Float32(ret) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).floatValue + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1172,7 +1217,7 @@ public func _bjs_PropertyHolder_floatValue_get(_self: UnsafeMutableRawPointer) - @_cdecl("bjs_PropertyHolder_floatValue_set") public func _bjs_PropertyHolder_floatValue_set(_self: UnsafeMutableRawPointer, value: Float32) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().floatValue = value + PropertyHolder.bridgeJSLiftParameter(_self).floatValue = Float.bridgeJSLiftParameter(value) #else fatalError("Only available on WebAssembly") #endif @@ -1182,8 +1227,8 @@ public func _bjs_PropertyHolder_floatValue_set(_self: UnsafeMutableRawPointer, v @_cdecl("bjs_PropertyHolder_doubleValue_get") public func _bjs_PropertyHolder_doubleValue_get(_self: UnsafeMutableRawPointer) -> Float64 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().doubleValue - return Float64(ret) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).doubleValue + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1193,7 +1238,7 @@ public func _bjs_PropertyHolder_doubleValue_get(_self: UnsafeMutableRawPointer) @_cdecl("bjs_PropertyHolder_doubleValue_set") public func _bjs_PropertyHolder_doubleValue_set(_self: UnsafeMutableRawPointer, value: Float64) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().doubleValue = value + PropertyHolder.bridgeJSLiftParameter(_self).doubleValue = Double.bridgeJSLiftParameter(value) #else fatalError("Only available on WebAssembly") #endif @@ -1203,8 +1248,8 @@ public func _bjs_PropertyHolder_doubleValue_set(_self: UnsafeMutableRawPointer, @_cdecl("bjs_PropertyHolder_boolValue_get") public func _bjs_PropertyHolder_boolValue_get(_self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().boolValue - return Int32(ret ? 1 : 0) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).boolValue + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1214,7 +1259,7 @@ public func _bjs_PropertyHolder_boolValue_get(_self: UnsafeMutableRawPointer) -> @_cdecl("bjs_PropertyHolder_boolValue_set") public func _bjs_PropertyHolder_boolValue_set(_self: UnsafeMutableRawPointer, value: Int32) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().boolValue = value == 1 + PropertyHolder.bridgeJSLiftParameter(_self).boolValue = Bool.bridgeJSLiftParameter(value) #else fatalError("Only available on WebAssembly") #endif @@ -1224,10 +1269,8 @@ public func _bjs_PropertyHolder_boolValue_set(_self: UnsafeMutableRawPointer, va @_cdecl("bjs_PropertyHolder_stringValue_get") public func _bjs_PropertyHolder_stringValue_get(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().stringValue - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = PropertyHolder.bridgeJSLiftParameter(_self).stringValue + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1235,13 +1278,9 @@ public func _bjs_PropertyHolder_stringValue_get(_self: UnsafeMutableRawPointer) @_expose(wasm, "bjs_PropertyHolder_stringValue_set") @_cdecl("bjs_PropertyHolder_stringValue_set") -public func _bjs_PropertyHolder_stringValue_set(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLen: Int32) -> Void { +public func _bjs_PropertyHolder_stringValue_set(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLength: Int32) -> Void { #if arch(wasm32) - let value = String(unsafeUninitializedCapacity: Int(valueLen)) { b in - _swift_js_init_memory(valueBytes, b.baseAddress.unsafelyUnwrapped) - return Int(valueLen) - } - Unmanaged.fromOpaque(_self).takeUnretainedValue().stringValue = value + PropertyHolder.bridgeJSLiftParameter(_self).stringValue = String.bridgeJSLiftParameter(valueBytes, valueLength) #else fatalError("Only available on WebAssembly") #endif @@ -1251,8 +1290,8 @@ public func _bjs_PropertyHolder_stringValue_set(_self: UnsafeMutableRawPointer, @_cdecl("bjs_PropertyHolder_readonlyInt_get") public func _bjs_PropertyHolder_readonlyInt_get(_self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().readonlyInt - return Int32(ret) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyInt + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1262,8 +1301,8 @@ public func _bjs_PropertyHolder_readonlyInt_get(_self: UnsafeMutableRawPointer) @_cdecl("bjs_PropertyHolder_readonlyFloat_get") public func _bjs_PropertyHolder_readonlyFloat_get(_self: UnsafeMutableRawPointer) -> Float32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().readonlyFloat - return Float32(ret) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyFloat + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1273,8 +1312,8 @@ public func _bjs_PropertyHolder_readonlyFloat_get(_self: UnsafeMutableRawPointer @_cdecl("bjs_PropertyHolder_readonlyDouble_get") public func _bjs_PropertyHolder_readonlyDouble_get(_self: UnsafeMutableRawPointer) -> Float64 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().readonlyDouble - return Float64(ret) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyDouble + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1284,8 +1323,8 @@ public func _bjs_PropertyHolder_readonlyDouble_get(_self: UnsafeMutableRawPointe @_cdecl("bjs_PropertyHolder_readonlyBool_get") public func _bjs_PropertyHolder_readonlyBool_get(_self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().readonlyBool - return Int32(ret ? 1 : 0) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyBool + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1295,10 +1334,8 @@ public func _bjs_PropertyHolder_readonlyBool_get(_self: UnsafeMutableRawPointer) @_cdecl("bjs_PropertyHolder_readonlyString_get") public func _bjs_PropertyHolder_readonlyString_get(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().readonlyString - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyString + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1308,8 +1345,8 @@ public func _bjs_PropertyHolder_readonlyString_get(_self: UnsafeMutableRawPointe @_cdecl("bjs_PropertyHolder_jsObject_get") public func _bjs_PropertyHolder_jsObject_get(_self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).jsObject + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1319,7 +1356,7 @@ public func _bjs_PropertyHolder_jsObject_get(_self: UnsafeMutableRawPointer) -> @_cdecl("bjs_PropertyHolder_jsObject_set") public func _bjs_PropertyHolder_jsObject_set(_self: UnsafeMutableRawPointer, value: Int32) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().jsObject = JSObject(id: UInt32(bitPattern: value)) + PropertyHolder.bridgeJSLiftParameter(_self).jsObject = JSObject.bridgeJSLiftParameter(value) #else fatalError("Only available on WebAssembly") #endif @@ -1329,8 +1366,8 @@ public func _bjs_PropertyHolder_jsObject_set(_self: UnsafeMutableRawPointer, val @_cdecl("bjs_PropertyHolder_sibling_get") public func _bjs_PropertyHolder_sibling_get(_self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().sibling - return Unmanaged.passRetained(ret).toOpaque() + let ret = PropertyHolder.bridgeJSLiftParameter(_self).sibling + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1340,7 +1377,7 @@ public func _bjs_PropertyHolder_sibling_get(_self: UnsafeMutableRawPointer) -> U @_cdecl("bjs_PropertyHolder_sibling_set") public func _bjs_PropertyHolder_sibling_set(_self: UnsafeMutableRawPointer, value: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().sibling = Unmanaged.fromOpaque(value).takeUnretainedValue() + PropertyHolder.bridgeJSLiftParameter(_self).sibling = SimplePropertyHolder.bridgeJSLiftParameter(value) #else fatalError("Only available on WebAssembly") #endif @@ -1350,10 +1387,8 @@ public func _bjs_PropertyHolder_sibling_set(_self: UnsafeMutableRawPointer, valu @_cdecl("bjs_PropertyHolder_lazyValue_get") public func _bjs_PropertyHolder_lazyValue_get(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().lazyValue - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = PropertyHolder.bridgeJSLiftParameter(_self).lazyValue + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1361,13 +1396,9 @@ public func _bjs_PropertyHolder_lazyValue_get(_self: UnsafeMutableRawPointer) -> @_expose(wasm, "bjs_PropertyHolder_lazyValue_set") @_cdecl("bjs_PropertyHolder_lazyValue_set") -public func _bjs_PropertyHolder_lazyValue_set(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLen: Int32) -> Void { +public func _bjs_PropertyHolder_lazyValue_set(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLength: Int32) -> Void { #if arch(wasm32) - let value = String(unsafeUninitializedCapacity: Int(valueLen)) { b in - _swift_js_init_memory(valueBytes, b.baseAddress.unsafelyUnwrapped) - return Int(valueLen) - } - Unmanaged.fromOpaque(_self).takeUnretainedValue().lazyValue = value + PropertyHolder.bridgeJSLiftParameter(_self).lazyValue = String.bridgeJSLiftParameter(valueBytes, valueLength) #else fatalError("Only available on WebAssembly") #endif @@ -1377,8 +1408,8 @@ public func _bjs_PropertyHolder_lazyValue_set(_self: UnsafeMutableRawPointer, va @_cdecl("bjs_PropertyHolder_computedReadonly_get") public func _bjs_PropertyHolder_computedReadonly_get(_self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().computedReadonly - return Int32(ret) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).computedReadonly + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1388,10 +1419,8 @@ public func _bjs_PropertyHolder_computedReadonly_get(_self: UnsafeMutableRawPoin @_cdecl("bjs_PropertyHolder_computedReadWrite_get") public func _bjs_PropertyHolder_computedReadWrite_get(_self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().computedReadWrite - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } + let ret = PropertyHolder.bridgeJSLiftParameter(_self).computedReadWrite + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1399,13 +1428,9 @@ public func _bjs_PropertyHolder_computedReadWrite_get(_self: UnsafeMutableRawPoi @_expose(wasm, "bjs_PropertyHolder_computedReadWrite_set") @_cdecl("bjs_PropertyHolder_computedReadWrite_set") -public func _bjs_PropertyHolder_computedReadWrite_set(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLen: Int32) -> Void { +public func _bjs_PropertyHolder_computedReadWrite_set(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLength: Int32) -> Void { #if arch(wasm32) - let value = String(unsafeUninitializedCapacity: Int(valueLen)) { b in - _swift_js_init_memory(valueBytes, b.baseAddress.unsafelyUnwrapped) - return Int(valueLen) - } - Unmanaged.fromOpaque(_self).takeUnretainedValue().computedReadWrite = value + PropertyHolder.bridgeJSLiftParameter(_self).computedReadWrite = String.bridgeJSLiftParameter(valueBytes, valueLength) #else fatalError("Only available on WebAssembly") #endif @@ -1415,8 +1440,8 @@ public func _bjs_PropertyHolder_computedReadWrite_set(_self: UnsafeMutableRawPoi @_cdecl("bjs_PropertyHolder_observedProperty_get") public func _bjs_PropertyHolder_observedProperty_get(_self: UnsafeMutableRawPointer) -> Int32 { #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().observedProperty - return Int32(ret) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).observedProperty + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1426,7 +1451,7 @@ public func _bjs_PropertyHolder_observedProperty_get(_self: UnsafeMutableRawPoin @_cdecl("bjs_PropertyHolder_observedProperty_set") public func _bjs_PropertyHolder_observedProperty_set(_self: UnsafeMutableRawPointer, value: Int32) -> Void { #if arch(wasm32) - Unmanaged.fromOpaque(_self).takeUnretainedValue().observedProperty = Int(value) + PropertyHolder.bridgeJSLiftParameter(_self).observedProperty = Int.bridgeJSLiftParameter(value) #else fatalError("Only available on WebAssembly") #endif @@ -1438,10 +1463,16 @@ public func _bjs_PropertyHolder_deinit(pointer: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(pointer).release() } -extension PropertyHolder: ConvertibleToJSValue { +extension PropertyHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { var jsValue: JSValue { + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_PropertyHolder_wrap") func _bjs_PropertyHolder_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_PropertyHolder_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_PropertyHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) } } \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ImportTS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ImportTS.swift index 255853fa..19bc82fc 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ImportTS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ImportTS.swift @@ -30,11 +30,11 @@ func jsRoundTripNumber(_ v: Double) throws(JSException) -> Double { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_jsRoundTripNumber(v) + let ret = bjs_jsRoundTripNumber(v.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return Double(ret) + return Double.bridgeJSLiftReturn(ret) } func jsRoundTripBool(_ v: Bool) throws(JSException) -> Bool { @@ -46,11 +46,11 @@ func jsRoundTripBool(_ v: Bool) throws(JSException) -> Bool { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_jsRoundTripBool(Int32(v ? 1 : 0)) + let ret = bjs_jsRoundTripBool(v.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return ret == 1 + return Bool.bridgeJSLiftReturn(ret) } func jsRoundTripString(_ v: String) throws(JSException) -> String { @@ -62,18 +62,11 @@ func jsRoundTripString(_ v: String) throws(JSException) -> String { fatalError("Only available on WebAssembly") } #endif - var v = v - let vId = v.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_jsRoundTripString(vId) + let ret = bjs_jsRoundTripString(v.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } + return String.bridgeJSLiftReturn(ret) } func jsThrowOrVoid(_ shouldThrow: Bool) throws(JSException) -> Void { @@ -85,7 +78,7 @@ func jsThrowOrVoid(_ shouldThrow: Bool) throws(JSException) -> Void { fatalError("Only available on WebAssembly") } #endif - bjs_jsThrowOrVoid(Int32(shouldThrow ? 1 : 0)) + bjs_jsThrowOrVoid(shouldThrow.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } @@ -100,11 +93,11 @@ func jsThrowOrNumber(_ shouldThrow: Bool) throws(JSException) -> Double { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_jsThrowOrNumber(Int32(shouldThrow ? 1 : 0)) + let ret = bjs_jsThrowOrNumber(shouldThrow.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return Double(ret) + return Double.bridgeJSLiftReturn(ret) } func jsThrowOrBool(_ shouldThrow: Bool) throws(JSException) -> Bool { @@ -116,11 +109,11 @@ func jsThrowOrBool(_ shouldThrow: Bool) throws(JSException) -> Bool { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_jsThrowOrBool(Int32(shouldThrow ? 1 : 0)) + let ret = bjs_jsThrowOrBool(shouldThrow.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return ret == 1 + return Bool.bridgeJSLiftReturn(ret) } func jsThrowOrString(_ shouldThrow: Bool) throws(JSException) -> String { @@ -132,14 +125,11 @@ func jsThrowOrString(_ shouldThrow: Bool) throws(JSException) -> String { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_jsThrowOrString(Int32(shouldThrow ? 1 : 0)) + let ret = bjs_jsThrowOrString(shouldThrow.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } + return String.bridgeJSLiftReturn(ret) } func runAsyncWorks() throws(JSException) -> JSPromise { @@ -155,18 +145,14 @@ func runAsyncWorks() throws(JSException) -> JSPromise { if let error = _swift_js_take_exception() { throw error } - return JSPromise(takingThis: ret) + return JSPromise.bridgeJSLiftReturn(ret) } -struct JsGreeter { - let this: JSObject +struct JsGreeter: _JSBridgedClass { + let jsObject: JSObject - init(this: JSObject) { - self.this = this - } - - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject } init(_ name: String, _ prefix: String) throws(JSException) { @@ -178,19 +164,11 @@ struct JsGreeter { fatalError("Only available on WebAssembly") } #endif - var name = name - let nameId = name.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - var prefix = prefix - let prefixId = prefix.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_JsGreeter_init(nameId, prefixId) + let ret = bjs_JsGreeter_init(name.bridgeJSLowerParameter(), prefix.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - self.this = JSObject(id: UInt32(bitPattern: ret)) + self.jsObject = JSObject(id: UInt32(bitPattern: ret)) } var name: String { @@ -203,14 +181,11 @@ struct JsGreeter { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_JsGreeter_name_get(Int32(bitPattern: self.this.id)) + let ret = bjs_JsGreeter_name_get(self.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } + return String.bridgeJSLiftReturn(ret) } } @@ -223,11 +198,7 @@ struct JsGreeter { fatalError("Only available on WebAssembly") } #endif - var newValue = newValue - let newValueId = newValue.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_JsGreeter_name_set(Int32(bitPattern: self.this.id), newValueId) + bjs_JsGreeter_name_set(self.bridgeJSLowerParameter(), newValue.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } @@ -243,14 +214,11 @@ struct JsGreeter { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_JsGreeter_prefix_get(Int32(bitPattern: self.this.id)) + let ret = bjs_JsGreeter_prefix_get(self.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } + return String.bridgeJSLiftReturn(ret) } } @@ -263,14 +231,11 @@ struct JsGreeter { fatalError("Only available on WebAssembly") } #endif - let ret = bjs_JsGreeter_greet(Int32(bitPattern: self.this.id)) + let ret = bjs_JsGreeter_greet(self.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } + return String.bridgeJSLiftReturn(ret) } func changeName(_ name: String) throws(JSException) -> Void { @@ -282,11 +247,7 @@ struct JsGreeter { fatalError("Only available on WebAssembly") } #endif - var name = name - let nameId = name.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_JsGreeter_changeName(Int32(bitPattern: self.this.id), nameId) + bjs_JsGreeter_changeName(self.bridgeJSLowerParameter(), name.bridgeJSLowerParameter()) if let error = _swift_js_take_exception() { throw error } diff --git a/Tests/JavaScriptEventLoopTests/WebWorkerDedicatedExecutorTests.swift b/Tests/JavaScriptEventLoopTests/WebWorkerDedicatedExecutorTests.swift index b6c2bd8d..aae8c2ce 100644 --- a/Tests/JavaScriptEventLoopTests/WebWorkerDedicatedExecutorTests.swift +++ b/Tests/JavaScriptEventLoopTests/WebWorkerDedicatedExecutorTests.swift @@ -2,6 +2,7 @@ import XCTest @testable import JavaScriptEventLoop +@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) final class WebWorkerDedicatedExecutorTests: XCTestCase { actor MyActor { let executor: WebWorkerDedicatedExecutor