From 180c0100c8ab7a6d18783bdab29892e4b33c0c0f Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sun, 8 Feb 2026 12:44:51 +0900 Subject: [PATCH 01/40] BridgeJS: show unified diff on snapshot mismatch (#600) --- .../BridgeJSToolTests/SnapshotTesting.swift | 41 ++++++++++++++++--- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/SnapshotTesting.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/SnapshotTesting.swift index ce7066a6d..de7ebd0c3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/SnapshotTesting.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/SnapshotTesting.swift @@ -22,17 +22,26 @@ func assertSnapshot( if FileManager.default.fileExists(atPath: snapshotPath.path) { let existingSnapshot = try String(contentsOf: snapshotPath, encoding: .utf8) - let ok = existingSnapshot == String(data: input, encoding: .utf8)! + let actual = String(data: input, encoding: .utf8)! + let ok = existingSnapshot == actual let actualFilePath = snapshotPath.path + ".actual" let updateSnapshots = ProcessInfo.processInfo.environment["UPDATE_SNAPSHOTS"] != nil - func buildComment() -> Comment { - "Snapshot mismatch: \(actualFilePath) \(snapshotPath.path)" - } + if !updateSnapshots { - #expect(ok, buildComment(), sourceLocation: sourceLocation) if !ok { - try input.write(to: URL(fileURLWithPath: actualFilePath)) + try actual.write(toFile: actualFilePath, atomically: true, encoding: .utf8) } + + let diff = ok ? nil : unifiedDiff(expectedPath: snapshotPath.path, actualPath: actualFilePath) + func buildComment() -> Comment { + var message = "Snapshot mismatch: \(actualFilePath) \(snapshotPath.path)" + if let diff { + message.append("\n\n" + diff) + } + return Comment(rawValue: message) + } + + #expect(ok, buildComment(), sourceLocation: sourceLocation) } else { try input.write(to: snapshotPath) } @@ -41,3 +50,23 @@ func assertSnapshot( #expect(Bool(false), "Snapshot created at \(snapshotPath.path)", sourceLocation: sourceLocation) } } + +private func unifiedDiff(expectedPath: String, actualPath: String) -> String? { + let process = Process() + process.executableURL = URL(fileURLWithPath: "/usr/bin/env") + process.arguments = ["diff", "-u", expectedPath, actualPath] + let output = Pipe() + process.standardOutput = output + process.standardError = Pipe() + + do { + try process.run() + } catch { + return nil + } + process.waitUntilExit() + + let data = output.fileHandleForReading.readDataToEndOfFile() + guard !data.isEmpty else { return nil } + return String(data: data, encoding: .utf8) +} From 6d103abc6438505220c45829fb6d48c12aa180fa Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 9 Feb 2026 08:54:16 +0900 Subject: [PATCH 02/40] [NFC] BridgeJS: Cover more types in closure snapshot tests (#602) --- .../Inputs/MacroSwift/SwiftClosure.swift | 53 +- .../BridgeJSCodegenTests/SwiftClosure.json | 2192 +++++++++++------ .../BridgeJSCodegenTests/SwiftClosure.swift | 1111 ++++++--- .../BridgeJSLinkTests/SwiftClosure.d.ts | 38 +- .../BridgeJSLinkTests/SwiftClosure.js | 745 +++--- 5 files changed, 2729 insertions(+), 1410 deletions(-) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClosure.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClosure.swift index 129f53b50..791b1b7a9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClosure.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClosure.swift @@ -9,41 +9,34 @@ import JavaScriptKit } @JS class TestProcessor { - private var transform: (String) -> String - - @JS init(transform: @escaping (String) -> String) { - self.transform = transform - } - - @JS func getTransform() -> (String) -> String - - @JS func processWithCustom(_ text: String, customTransform: (String) -> String) -> String + @JS init(transform: @escaping (String) -> String) {} +} - @JS func printTogether( - person: Person, - name: String, - ratio: Double, - customTransform: (Person?, String?, Double?) -> String - ) -> String +@JS func roundtripString(_ stringClosure: (String) -> String) -> (String) -> String +@JS func roundtripInt(_ intClosure: (Int) -> Int) -> (Int) -> Int +@JS func roundtripBool(_ boolClosure: (Bool) -> Bool) -> (Bool) -> Bool +@JS func roundtripFloat(_ floatClosure: (Float) -> Float) -> (Float) -> Float +@JS func roundtripDouble(_ doubleClosure: (Double) -> Double) -> (Double) -> Double - @JS func roundtrip(_ personClosure: (Person) -> String) -> (Person) -> String - @JS func roundtripOptional(_ personClosure: (Person?) -> String) -> (Person?) -> String +@JS func roundtripOptionalString(_ stringClosure: (String?) -> String?) -> (String?) -> String? +@JS func roundtripOptionalInt(_ intClosure: (Int?) -> Int?) -> (Int?) -> Int? +@JS func roundtripOptionalBool(_ boolClosure: (Bool?) -> Bool?) -> (Bool?) -> Bool? +@JS func roundtripOptionalFloat(_ floatClosure: (Float?) -> Float?) -> (Float?) -> Float? +@JS func roundtripOptionalDouble(_ doubleClosure: (Double?) -> Double?) -> (Double?) -> Double? - @JS func processDirection(_ callback: (Direction) -> String) -> String - @JS func processTheme(_ callback: (Theme) -> String) -> String - @JS func processHttpStatus(_ callback: (HttpStatus) -> Int) -> Int - @JS func processAPIResult(_ callback: (APIResult) -> String) -> String +@JS func roundtripPerson(_ personClosure: (Person) -> Person) -> (Person) -> Person +@JS func roundtripOptionalPerson(_ personClosure: (Person?) -> Person?) -> (Person?) -> Person? - @JS func makeDirectionChecker() -> (Direction) -> Bool - @JS func makeThemeValidator() -> (Theme) -> Bool - @JS func makeStatusCodeExtractor() -> (HttpStatus) -> Int - @JS func makeAPIResultHandler() -> (APIResult) -> String +@JS func roundtripDirection(_ callback: (Direction) -> Direction) -> (Direction) -> Direction +@JS func roundtripTheme(_ callback: (Theme) -> Theme) -> (Theme) -> Theme +@JS func roundtripHttpStatus(_ callback: (HttpStatus) -> HttpStatus) -> (HttpStatus) -> HttpStatus +@JS func roundtripAPIResult(_ callback: (APIResult) -> APIResult) -> (APIResult) -> APIResult - @JS func processOptionalDirection(_ callback: (Direction?) -> String) -> String - @JS func processOptionalTheme(_ callback: (Theme?) -> String) -> String - @JS func processOptionalAPIResult(_ callback: (APIResult?) -> String) -> String - @JS func makeOptionalDirectionFormatter() -> (Direction?) -> String -} +@JS func roundtripOptionalDirection(_ callback: (Direction?) -> Direction?) -> (Direction?) -> Direction? +@JS func roundtripOptionalTheme(_ callback: (Theme?) -> Theme?) -> (Theme?) -> Theme? +@JS func roundtripOptionalHttpStatus(_ callback: (HttpStatus?) -> HttpStatus?) -> (HttpStatus?) -> HttpStatus? +@JS func roundtripOptionalAPIResult(_ callback: (APIResult?) -> APIResult?) -> (APIResult?) -> APIResult? +@JS func roundtripOptionalDirection(_ callback: (Direction?) -> Direction?) -> (Direction?) -> Direction? @JS enum Direction { case north diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.json index ee551fa47..11c6cb893 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.json @@ -70,236 +70,239 @@ ] }, "methods" : [ + + ], + "name" : "TestProcessor", + "properties" : [ + + ], + "swiftCallName" : "TestProcessor" + } + ], + "enums" : [ + { + "cases" : [ { - "abiName" : "bjs_TestProcessor_getTransform", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "getTransform", - "parameters" : [ + "associatedValues" : [ ], - "returnType" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "10TestModuleSS_SS", - "moduleName" : "TestModule", - "parameters" : [ - { - "string" : { + "name" : "north" + }, + { + "associatedValues" : [ - } - } - ], - "returnType" : { - "string" : { + ], + "name" : "south" + }, + { + "associatedValues" : [ - } - } - }, - "useJSTypedClosure" : false - } - } + ], + "name" : "east" }, { - "abiName" : "bjs_TestProcessor_processWithCustom", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "processWithCustom", - "parameters" : [ - { - "label" : "_", - "name" : "text", - "type" : { - "string" : { + "associatedValues" : [ - } - } - }, - { - "label" : "customTransform", - "name" : "customTransform", - "type" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "10TestModuleSS_SS", - "moduleName" : "TestModule", - "parameters" : [ - { - "string" : { + ], + "name" : "west" + } + ], + "emitStyle" : "const", + "name" : "Direction", + "staticMethods" : [ - } - } - ], - "returnType" : { - "string" : { + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Direction", + "tsFullPath" : "Direction" + }, + { + "cases" : [ + { + "associatedValues" : [ - } - } - }, - "useJSTypedClosure" : false - } - } - } ], - "returnType" : { - "string" : { + "name" : "light", + "rawValue" : "light" + }, + { + "associatedValues" : [ - } - } + ], + "name" : "dark", + "rawValue" : "dark" }, { - "abiName" : "bjs_TestProcessor_printTogether", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "printTogether", - "parameters" : [ + "associatedValues" : [ + + ], + "name" : "auto", + "rawValue" : "auto" + } + ], + "emitStyle" : "const", + "name" : "Theme", + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Theme", + "tsFullPath" : "Theme" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "ok", + "rawValue" : "200" + }, + { + "associatedValues" : [ + + ], + "name" : "notFound", + "rawValue" : "404" + }, + { + "associatedValues" : [ + + ], + "name" : "serverError", + "rawValue" : "500" + }, + { + "associatedValues" : [ + + ], + "name" : "unknown", + "rawValue" : "-1" + } + ], + "emitStyle" : "const", + "name" : "HttpStatus", + "rawType" : "Int", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "HttpStatus", + "tsFullPath" : "HttpStatus" + }, + { + "cases" : [ + { + "associatedValues" : [ { - "label" : "person", - "name" : "person", "type" : { - "swiftHeapObject" : { - "_0" : "Person" + "string" : { + } } - }, + } + ], + "name" : "success" + }, + { + "associatedValues" : [ { - "label" : "name", - "name" : "name", "type" : { - "string" : { + "int" : { } } - }, + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ { - "label" : "ratio", - "name" : "ratio", "type" : { - "double" : { + "bool" : { } } - }, + } + ], + "name" : "flag" + }, + { + "associatedValues" : [ { - "label" : "customTransform", - "name" : "customTransform", "type" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "10TestModuleSq6PersonCSqSSSqSd_SS", - "moduleName" : "TestModule", - "parameters" : [ - { - "nullable" : { - "_0" : { - "swiftHeapObject" : { - "_0" : "Person" - } - }, - "_1" : "null" - } - }, - { - "nullable" : { - "_0" : { - "string" : { - - } - }, - "_1" : "null" - } - }, - { - "nullable" : { - "_0" : { - "double" : { - - } - }, - "_1" : "null" - } - } - ], - "returnType" : { - "string" : { + "float" : { - } - } - }, - "useJSTypedClosure" : false } } } ], - "returnType" : { - "string" : { - - } - } + "name" : "rate" }, { - "abiName" : "bjs_TestProcessor_roundtrip", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "roundtrip", - "parameters" : [ + "associatedValues" : [ { - "label" : "_", - "name" : "personClosure", "type" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "10TestModule6PersonC_SS", - "moduleName" : "TestModule", - "parameters" : [ - { - "swiftHeapObject" : { - "_0" : "Person" - } - } - ], - "returnType" : { - "string" : { + "double" : { - } - } - }, - "useJSTypedClosure" : false } } } ], - "returnType" : { + "name" : "precise" + }, + { + "associatedValues" : [ + + ], + "name" : "info" + } + ], + "emitStyle" : "const", + "name" : "APIResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "APIResult", + "tsFullPath" : "APIResult" + } + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_roundtripString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripString", + "parameters" : [ + { + "label" : "_", + "name" : "stringClosure", + "type" : { "closure" : { "_0" : { "isAsync" : false, "isThrows" : false, - "mangleName" : "10TestModule6PersonC_SS", + "mangleName" : "10TestModuleSS_SS", "moduleName" : "TestModule", "parameters" : [ { - "swiftHeapObject" : { - "_0" : "Person" + "string" : { + } } ], @@ -312,70 +315,60 @@ "useJSTypedClosure" : false } } - }, - { - "abiName" : "bjs_TestProcessor_roundtripOptional", - "effects" : { + } + ], + "returnType" : { + "closure" : { + "_0" : { "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "roundtripOptional", - "parameters" : [ - { - "label" : "_", - "name" : "personClosure", - "type" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "10TestModuleSq6PersonC_SS", - "moduleName" : "TestModule", - "parameters" : [ - { - "nullable" : { - "_0" : { - "swiftHeapObject" : { - "_0" : "Person" - } - }, - "_1" : "null" - } - } - ], - "returnType" : { - "string" : { + "isThrows" : false, + "mangleName" : "10TestModuleSS_SS", + "moduleName" : "TestModule", + "parameters" : [ + { + "string" : { - } - } - }, - "useJSTypedClosure" : false } } + ], + "returnType" : { + "string" : { + + } } - ], - "returnType" : { + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripInt", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripInt", + "parameters" : [ + { + "label" : "_", + "name" : "intClosure", + "type" : { "closure" : { "_0" : { "isAsync" : false, "isThrows" : false, - "mangleName" : "10TestModuleSq6PersonC_SS", + "mangleName" : "10TestModuleSi_Si", "moduleName" : "TestModule", "parameters" : [ { - "nullable" : { - "_0" : { - "swiftHeapObject" : { - "_0" : "Person" - } - }, - "_1" : "null" + "int" : { + } } ], "returnType" : { - "string" : { + "int" : { } } @@ -383,208 +376,121 @@ "useJSTypedClosure" : false } } - }, - { - "abiName" : "bjs_TestProcessor_processDirection", - "effects" : { + } + ], + "returnType" : { + "closure" : { + "_0" : { "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "processDirection", - "parameters" : [ - { - "label" : "_", - "name" : "callback", - "type" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "10TestModule9DirectionO_SS", - "moduleName" : "TestModule", - "parameters" : [ - { - "caseEnum" : { - "_0" : "Direction" - } - } - ], - "returnType" : { - "string" : { + "isThrows" : false, + "mangleName" : "10TestModuleSi_Si", + "moduleName" : "TestModule", + "parameters" : [ + { + "int" : { - } - } - }, - "useJSTypedClosure" : false } } - } - ], - "returnType" : { - "string" : { - - } - } - }, - { - "abiName" : "bjs_TestProcessor_processTheme", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "processTheme", - "parameters" : [ - { - "label" : "_", - "name" : "callback", - "type" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "10TestModule5ThemeO_SS", - "moduleName" : "TestModule", - "parameters" : [ - { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" - } - } - ], - "returnType" : { - "string" : { + ], + "returnType" : { + "int" : { - } - } - }, - "useJSTypedClosure" : false - } } } - ], - "returnType" : { - "string" : { - - } - } - }, - { - "abiName" : "bjs_TestProcessor_processHttpStatus", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false }, - "name" : "processHttpStatus", - "parameters" : [ - { - "label" : "_", - "name" : "callback", - "type" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "10TestModule10HttpStatusO_Si", - "moduleName" : "TestModule", - "parameters" : [ - { - "rawValueEnum" : { - "_0" : "HttpStatus", - "_1" : "Int" - } - } - ], - "returnType" : { - "int" : { + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripBool", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripBool", + "parameters" : [ + { + "label" : "_", + "name" : "boolClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSb_Sb", + "moduleName" : "TestModule", + "parameters" : [ + { + "bool" : { - } } - }, - "useJSTypedClosure" : false - } - } - } - ], - "returnType" : { - "int" : { + } + ], + "returnType" : { + "bool" : { + } + } + }, + "useJSTypedClosure" : false } } - }, - { - "abiName" : "bjs_TestProcessor_processAPIResult", - "effects" : { + } + ], + "returnType" : { + "closure" : { + "_0" : { "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "processAPIResult", - "parameters" : [ - { - "label" : "_", - "name" : "callback", - "type" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "10TestModule9APIResultO_SS", - "moduleName" : "TestModule", - "parameters" : [ - { - "associatedValueEnum" : { - "_0" : "APIResult" - } - } - ], - "returnType" : { - "string" : { + "isThrows" : false, + "mangleName" : "10TestModuleSb_Sb", + "moduleName" : "TestModule", + "parameters" : [ + { + "bool" : { - } - } - }, - "useJSTypedClosure" : false } } - } - ], - "returnType" : { - "string" : { + ], + "returnType" : { + "bool" : { + } } - } - }, - { - "abiName" : "bjs_TestProcessor_makeDirectionChecker", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false }, - "name" : "makeDirectionChecker", - "parameters" : [ - - ], - "returnType" : { + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripFloat", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripFloat", + "parameters" : [ + { + "label" : "_", + "name" : "floatClosure", + "type" : { "closure" : { "_0" : { "isAsync" : false, "isThrows" : false, - "mangleName" : "10TestModule9DirectionO_Sb", + "mangleName" : "10TestModuleSf_Sf", "moduleName" : "TestModule", "parameters" : [ { - "caseEnum" : { - "_0" : "Direction" + "float" : { + } } ], "returnType" : { - "bool" : { + "float" : { } } @@ -592,35 +498,60 @@ "useJSTypedClosure" : false } } - }, - { - "abiName" : "bjs_TestProcessor_makeThemeValidator", - "effects" : { + } + ], + "returnType" : { + "closure" : { + "_0" : { "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "makeThemeValidator", - "parameters" : [ + "isThrows" : false, + "mangleName" : "10TestModuleSf_Sf", + "moduleName" : "TestModule", + "parameters" : [ + { + "float" : { - ], - "returnType" : { + } + } + ], + "returnType" : { + "float" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripDouble", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripDouble", + "parameters" : [ + { + "label" : "_", + "name" : "doubleClosure", + "type" : { "closure" : { "_0" : { "isAsync" : false, "isThrows" : false, - "mangleName" : "10TestModule5ThemeO_Sb", + "mangleName" : "10TestModuleSd_Sd", "moduleName" : "TestModule", "parameters" : [ { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" + "double" : { + } } ], "returnType" : { - "bool" : { + "double" : { } } @@ -628,247 +559,300 @@ "useJSTypedClosure" : false } } - }, - { - "abiName" : "bjs_TestProcessor_makeStatusCodeExtractor", - "effects" : { + } + ], + "returnType" : { + "closure" : { + "_0" : { "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "makeStatusCodeExtractor", - "parameters" : [ + "isThrows" : false, + "mangleName" : "10TestModuleSd_Sd", + "moduleName" : "TestModule", + "parameters" : [ + { + "double" : { - ], - "returnType" : { + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalString", + "parameters" : [ + { + "label" : "_", + "name" : "stringClosure", + "type" : { "closure" : { "_0" : { "isAsync" : false, "isThrows" : false, - "mangleName" : "10TestModule10HttpStatusO_Si", + "mangleName" : "10TestModuleSqSS_SqSS", "moduleName" : "TestModule", "parameters" : [ { - "rawValueEnum" : { - "_0" : "HttpStatus", - "_1" : "Int" + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" } } ], "returnType" : { - "int" : { + "nullable" : { + "_0" : { + "string" : { + } + }, + "_1" : "null" } } }, "useJSTypedClosure" : false } } - }, - { - "abiName" : "bjs_TestProcessor_makeAPIResultHandler", - "effects" : { + } + ], + "returnType" : { + "closure" : { + "_0" : { "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "makeAPIResultHandler", - "parameters" : [ + "isThrows" : false, + "mangleName" : "10TestModuleSqSS_SqSS", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "string" : { - ], - "returnType" : { + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalInt", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalInt", + "parameters" : [ + { + "label" : "_", + "name" : "intClosure", + "type" : { "closure" : { "_0" : { "isAsync" : false, "isThrows" : false, - "mangleName" : "10TestModule9APIResultO_SS", + "mangleName" : "10TestModuleSqSi_SqSi", "moduleName" : "TestModule", "parameters" : [ { - "associatedValueEnum" : { - "_0" : "APIResult" + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" } } ], "returnType" : { - "string" : { + "nullable" : { + "_0" : { + "int" : { + } + }, + "_1" : "null" } } }, "useJSTypedClosure" : false } } - }, - { - "abiName" : "bjs_TestProcessor_processOptionalDirection", - "effects" : { + } + ], + "returnType" : { + "closure" : { + "_0" : { "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "processOptionalDirection", - "parameters" : [ - { - "label" : "_", - "name" : "callback", - "type" : { - "closure" : { + "isThrows" : false, + "mangleName" : "10TestModuleSqSi_SqSi", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "10TestModuleSq9DirectionO_SS", - "moduleName" : "TestModule", - "parameters" : [ - { - "nullable" : { - "_0" : { - "caseEnum" : { - "_0" : "Direction" - } - }, - "_1" : "null" - } - } - ], - "returnType" : { - "string" : { + "int" : { - } } }, - "useJSTypedClosure" : false + "_1" : "null" } } - } - ], - "returnType" : { - "string" : { + ], + "returnType" : { + "nullable" : { + "_0" : { + "int" : { + } + }, + "_1" : "null" + } } - } - }, - { - "abiName" : "bjs_TestProcessor_processOptionalTheme", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false }, - "name" : "processOptionalTheme", - "parameters" : [ - { - "label" : "_", - "name" : "callback", - "type" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "10TestModuleSq5ThemeO_SS", - "moduleName" : "TestModule", - "parameters" : [ - { - "nullable" : { - "_0" : { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" - } - }, - "_1" : "null" + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalBool", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalBool", + "parameters" : [ + { + "label" : "_", + "name" : "boolClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSqSb_SqSb", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "bool" : { + } - } - ], - "returnType" : { - "string" : { + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "bool" : { } - } - }, - "useJSTypedClosure" : false + }, + "_1" : "null" + } } - } - } - ], - "returnType" : { - "string" : { - + }, + "useJSTypedClosure" : false } } - }, - { - "abiName" : "bjs_TestProcessor_processOptionalAPIResult", - "effects" : { + } + ], + "returnType" : { + "closure" : { + "_0" : { "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "processOptionalAPIResult", - "parameters" : [ - { - "label" : "_", - "name" : "callback", - "type" : { - "closure" : { + "isThrows" : false, + "mangleName" : "10TestModuleSqSb_SqSb", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "10TestModuleSq9APIResultO_SS", - "moduleName" : "TestModule", - "parameters" : [ - { - "nullable" : { - "_0" : { - "associatedValueEnum" : { - "_0" : "APIResult" - } - }, - "_1" : "null" - } - } - ], - "returnType" : { - "string" : { + "bool" : { - } } }, - "useJSTypedClosure" : false + "_1" : "null" } } - } - ], - "returnType" : { - "string" : { + ], + "returnType" : { + "nullable" : { + "_0" : { + "bool" : { + } + }, + "_1" : "null" + } } - } - }, - { - "abiName" : "bjs_TestProcessor_makeOptionalDirectionFormatter", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false }, - "name" : "makeOptionalDirectionFormatter", - "parameters" : [ - - ], - "returnType" : { + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalFloat", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalFloat", + "parameters" : [ + { + "label" : "_", + "name" : "floatClosure", + "type" : { "closure" : { "_0" : { "isAsync" : false, "isThrows" : false, - "mangleName" : "10TestModuleSq9DirectionO_SS", + "mangleName" : "10TestModuleSqSf_SqSf", "moduleName" : "TestModule", "parameters" : [ { "nullable" : { "_0" : { - "caseEnum" : { - "_0" : "Direction" + "float" : { + } }, "_1" : "null" @@ -876,8 +860,13 @@ } ], "returnType" : { - "string" : { + "nullable" : { + "_0" : { + "float" : { + } + }, + "_1" : "null" } } }, @@ -886,215 +875,928 @@ } } ], - "name" : "TestProcessor", - "properties" : [ - - ], - "swiftCallName" : "TestProcessor" - } - ], - "enums" : [ - { - "cases" : [ - { - "associatedValues" : [ - - ], - "name" : "north" - }, - { - "associatedValues" : [ - - ], - "name" : "south" - }, - { - "associatedValues" : [ + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSqSf_SqSf", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "float" : { - ], - "name" : "east" - }, - { - "associatedValues" : [ + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "float" : { - ], - "name" : "west" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false } - ], - "emitStyle" : "const", - "name" : "Direction", - "staticMethods" : [ - - ], - "staticProperties" : [ - - ], - "swiftCallName" : "Direction", - "tsFullPath" : "Direction" + } }, { - "cases" : [ - { - "associatedValues" : [ - - ], - "name" : "light", - "rawValue" : "light" - }, + "abiName" : "bjs_roundtripOptionalDouble", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalDouble", + "parameters" : [ { - "associatedValues" : [ + "label" : "_", + "name" : "doubleClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSqSd_SqSd", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "double" : { - ], - "name" : "dark", - "rawValue" : "dark" - }, - { - "associatedValues" : [ + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "double" : { - ], - "name" : "auto", - "rawValue" : "auto" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } } ], - "emitStyle" : "const", - "name" : "Theme", - "rawType" : "String", - "staticMethods" : [ + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSqSd_SqSd", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "double" : { - ], - "staticProperties" : [ + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "double" : { - ], - "swiftCallName" : "Theme", - "tsFullPath" : "Theme" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } }, { - "cases" : [ - { - "associatedValues" : [ - - ], - "name" : "ok", - "rawValue" : "200" - }, - { - "associatedValues" : [ - - ], - "name" : "notFound", - "rawValue" : "404" - }, - { - "associatedValues" : [ - - ], - "name" : "serverError", - "rawValue" : "500" - }, + "abiName" : "bjs_roundtripPerson", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripPerson", + "parameters" : [ { - "associatedValues" : [ - - ], - "name" : "unknown", - "rawValue" : "-1" + "label" : "_", + "name" : "personClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule6PersonC_6PersonC", + "moduleName" : "TestModule", + "parameters" : [ + { + "swiftHeapObject" : { + "_0" : "Person" + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Person" + } + } + }, + "useJSTypedClosure" : false + } + } } ], - "emitStyle" : "const", - "name" : "HttpStatus", - "rawType" : "Int", - "staticMethods" : [ - - ], - "staticProperties" : [ - - ], - "swiftCallName" : "HttpStatus", - "tsFullPath" : "HttpStatus" + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule6PersonC_6PersonC", + "moduleName" : "TestModule", + "parameters" : [ + { + "swiftHeapObject" : { + "_0" : "Person" + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Person" + } + } + }, + "useJSTypedClosure" : false + } + } }, { - "cases" : [ + "abiName" : "bjs_roundtripOptionalPerson", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalPerson", + "parameters" : [ { - "associatedValues" : [ - { - "type" : { - "string" : { - + "label" : "_", + "name" : "personClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq6PersonC_Sq6PersonC", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Person" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Person" + } + }, + "_1" : "null" + } } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq6PersonC_Sq6PersonC", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Person" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Person" + } + }, + "_1" : "null" } } - ], - "name" : "success" - }, + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripDirection", + "parameters" : [ { - "associatedValues" : [ - { - "type" : { - "int" : { - + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule9DirectionO_9DirectionO", + "moduleName" : "TestModule", + "parameters" : [ + { + "caseEnum" : { + "_0" : "Direction" + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "Direction" + } } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule9DirectionO_9DirectionO", + "moduleName" : "TestModule", + "parameters" : [ + { + "caseEnum" : { + "_0" : "Direction" + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "Direction" } } - ], - "name" : "failure" - }, + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripTheme", + "parameters" : [ { - "associatedValues" : [ - { - "type" : { - "bool" : { - + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule5ThemeO_5ThemeO", + "moduleName" : "TestModule", + "parameters" : [ + { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule5ThemeO_5ThemeO", + "moduleName" : "TestModule", + "parameters" : [ + { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" } } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } } - ], - "name" : "flag" - }, + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripHttpStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripHttpStatus", + "parameters" : [ { - "associatedValues" : [ - { - "type" : { - "float" : { - + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule10HttpStatusO_10HttpStatusO", + "moduleName" : "TestModule", + "parameters" : [ + { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule10HttpStatusO_10HttpStatusO", + "moduleName" : "TestModule", + "parameters" : [ + { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" } } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } } - ], - "name" : "rate" - }, + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripAPIResult", + "parameters" : [ { - "associatedValues" : [ - { - "type" : { - "double" : { - + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule9APIResultO_9APIResultO", + "moduleName" : "TestModule", + "parameters" : [ + { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule9APIResultO_9APIResultO", + "moduleName" : "TestModule", + "parameters" : [ + { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" } } - ], - "name" : "precise" - }, + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalDirection", + "parameters" : [ { - "associatedValues" : [ - - ], - "name" : "info" + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq9DirectionO_Sq9DirectionO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } } ], - "emitStyle" : "const", - "name" : "APIResult", - "staticMethods" : [ - + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq9DirectionO_Sq9DirectionO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalTheme", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq5ThemeO_Sq5ThemeO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } ], - "staticProperties" : [ - + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq5ThemeO_Sq5ThemeO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalHttpStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalHttpStatus", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq10HttpStatusO_Sq10HttpStatusO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } ], - "swiftCallName" : "APIResult", - "tsFullPath" : "APIResult" + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq10HttpStatusO_Sq10HttpStatusO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalAPIResult", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq9APIResultO_Sq9APIResultO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq9APIResultO_Sq9APIResultO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalDirection", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq9DirectionO_Sq9DirectionO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq9DirectionO_Sq9DirectionO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } } - ], - "exposeToGlobal" : false, - "functions" : [ - ], "protocols" : [ diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift index e659988d1..8aa9efd65 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift @@ -1,30 +1,30 @@ #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule10HttpStatusO_Si") -fileprivate func invoke_js_callback_TestModule_10TestModule10HttpStatusO_Si(_ callback: Int32, _ param0: Int32) -> Int32 +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule10HttpStatusO_10HttpStatusO") +fileprivate func invoke_js_callback_TestModule_10TestModule10HttpStatusO_10HttpStatusO(_ callback: Int32, _ param0: Int32) -> Int32 #else -fileprivate func invoke_js_callback_TestModule_10TestModule10HttpStatusO_Si(_ callback: Int32, _ param0: Int32) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModule10HttpStatusO_10HttpStatusO(_ callback: Int32, _ param0: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule10HttpStatusO_Si") -fileprivate func make_swift_closure_TestModule_10TestModule10HttpStatusO_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO") +fileprivate func make_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 #else -fileprivate func make_swift_closure_TestModule_10TestModule10HttpStatusO_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { +fileprivate func make_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -private enum _BJS_Closure_10TestModule10HttpStatusO_Si { - static func bridgeJSLift(_ callbackId: Int32) -> (HttpStatus) -> Int { +private enum _BJS_Closure_10TestModule10HttpStatusO_10HttpStatusO { + static func bridgeJSLift(_ callbackId: Int32) -> (HttpStatus) -> HttpStatus { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) let callbackValue = callback.bridgeJSLowerParameter() let param0Value = param0.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModule10HttpStatusO_Si(callbackValue, param0Value) - return Int.bridgeJSLiftReturn(ret) + let ret = invoke_js_callback_TestModule_10TestModule10HttpStatusO_10HttpStatusO(callbackValue, param0Value) + return HttpStatus.bridgeJSLiftReturn(ret) #else fatalError("Only available on WebAssembly") #endif @@ -32,10 +32,10 @@ private enum _BJS_Closure_10TestModule10HttpStatusO_Si { } } -extension JSTypedClosure where Signature == (HttpStatus) -> Int { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (HttpStatus) -> Int) { +extension JSTypedClosure where Signature == (HttpStatus) -> HttpStatus { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (HttpStatus) -> HttpStatus) { self.init( - makeClosure: make_swift_closure_TestModule_10TestModule10HttpStatusO_Si, + makeClosure: make_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO, body: body, fileID: fileID, line: line @@ -43,11 +43,11 @@ extension JSTypedClosure where Signature == (HttpStatus) -> Int { } } -@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule10HttpStatusO_Si") -@_cdecl("invoke_swift_closure_TestModule_10TestModule10HttpStatusO_Si") -public func _invoke_swift_closure_TestModule_10TestModule10HttpStatusO_Si(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO") +@_cdecl("invoke_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO") +public func _invoke_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { #if arch(wasm32) - let closure = Unmanaged<_BridgeJSTypedClosureBox<(HttpStatus) -> Int>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let closure = Unmanaged<_BridgeJSTypedClosureBox<(HttpStatus) -> HttpStatus>>.fromOpaque(boxPtr).takeUnretainedValue().closure let result = closure(HttpStatus.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else @@ -56,32 +56,32 @@ public func _invoke_swift_closure_TestModule_10TestModule10HttpStatusO_Si(_ boxP } #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule5ThemeO_SS") -fileprivate func invoke_js_callback_TestModule_10TestModule5ThemeO_SS(_ callback: Int32, _ param0: Int32) -> Int32 +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO") +fileprivate func invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO(_ callback: Int32, _ param0: Int32) -> Int32 #else -fileprivate func invoke_js_callback_TestModule_10TestModule5ThemeO_SS(_ callback: Int32, _ param0: Int32) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO(_ callback: Int32, _ param0: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule5ThemeO_SS") -fileprivate func make_swift_closure_TestModule_10TestModule5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO") +fileprivate func make_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 #else -fileprivate func make_swift_closure_TestModule_10TestModule5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { +fileprivate func make_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -private enum _BJS_Closure_10TestModule5ThemeO_SS { - static func bridgeJSLift(_ callbackId: Int32) -> (Theme) -> String { +private enum _BJS_Closure_10TestModule5ThemeO_5ThemeO { + static func bridgeJSLift(_ callbackId: Int32) -> (Theme) -> Theme { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) let callbackValue = callback.bridgeJSLowerParameter() let param0Value = param0.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModule5ThemeO_SS(callbackValue, param0Value) - return String.bridgeJSLiftReturn(ret) + let ret = invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO(callbackValue, param0Value) + return Theme.bridgeJSLiftReturn(ret) #else fatalError("Only available on WebAssembly") #endif @@ -89,10 +89,10 @@ private enum _BJS_Closure_10TestModule5ThemeO_SS { } } -extension JSTypedClosure where Signature == (Theme) -> String { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Theme) -> String) { +extension JSTypedClosure where Signature == (Theme) -> Theme { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Theme) -> Theme) { self.init( - makeClosure: make_swift_closure_TestModule_10TestModule5ThemeO_SS, + makeClosure: make_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO, body: body, fileID: fileID, line: line @@ -100,11 +100,11 @@ extension JSTypedClosure where Signature == (Theme) -> String { } } -@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule5ThemeO_SS") -@_cdecl("invoke_swift_closure_TestModule_10TestModule5ThemeO_SS") -public func _invoke_swift_closure_TestModule_10TestModule5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO") +@_cdecl("invoke_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO") +public func _invoke_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { #if arch(wasm32) - let closure = Unmanaged<_BridgeJSTypedClosureBox<(Theme) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Theme) -> Theme>>.fromOpaque(boxPtr).takeUnretainedValue().closure let result = closure(Theme.bridgeJSLiftParameter(param0Bytes, param0Length)) return result.bridgeJSLowerReturn() #else @@ -113,32 +113,32 @@ public func _invoke_swift_closure_TestModule_10TestModule5ThemeO_SS(_ boxPtr: Un } #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule5ThemeO_Sb") -fileprivate func invoke_js_callback_TestModule_10TestModule5ThemeO_Sb(_ callback: Int32, _ param0: Int32) -> Int32 +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule6PersonC_6PersonC") +fileprivate func invoke_js_callback_TestModule_10TestModule6PersonC_6PersonC(_ callback: Int32, _ param0: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer #else -fileprivate func invoke_js_callback_TestModule_10TestModule5ThemeO_Sb(_ callback: Int32, _ param0: Int32) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModule6PersonC_6PersonC(_ callback: Int32, _ param0: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { fatalError("Only available on WebAssembly") } #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule5ThemeO_Sb") -fileprivate func make_swift_closure_TestModule_10TestModule5ThemeO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule6PersonC_6PersonC") +fileprivate func make_swift_closure_TestModule_10TestModule6PersonC_6PersonC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 #else -fileprivate func make_swift_closure_TestModule_10TestModule5ThemeO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { +fileprivate func make_swift_closure_TestModule_10TestModule6PersonC_6PersonC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -private enum _BJS_Closure_10TestModule5ThemeO_Sb { - static func bridgeJSLift(_ callbackId: Int32) -> (Theme) -> Bool { +private enum _BJS_Closure_10TestModule6PersonC_6PersonC { + static func bridgeJSLift(_ callbackId: Int32) -> (Person) -> Person { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) let callbackValue = callback.bridgeJSLowerParameter() - let param0Value = param0.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModule5ThemeO_Sb(callbackValue, param0Value) - return Bool.bridgeJSLiftReturn(ret) + let param0Pointer = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModule6PersonC_6PersonC(callbackValue, param0Pointer) + return Person.bridgeJSLiftReturn(ret) #else fatalError("Only available on WebAssembly") #endif @@ -146,10 +146,10 @@ private enum _BJS_Closure_10TestModule5ThemeO_Sb { } } -extension JSTypedClosure where Signature == (Theme) -> Bool { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Theme) -> Bool) { +extension JSTypedClosure where Signature == (Person) -> Person { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Person) -> Person) { self.init( - makeClosure: make_swift_closure_TestModule_10TestModule5ThemeO_Sb, + makeClosure: make_swift_closure_TestModule_10TestModule6PersonC_6PersonC, body: body, fileID: fileID, line: line @@ -157,12 +157,12 @@ extension JSTypedClosure where Signature == (Theme) -> Bool { } } -@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule5ThemeO_Sb") -@_cdecl("invoke_swift_closure_TestModule_10TestModule5ThemeO_Sb") -public func _invoke_swift_closure_TestModule_10TestModule5ThemeO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule6PersonC_6PersonC") +@_cdecl("invoke_swift_closure_TestModule_10TestModule6PersonC_6PersonC") +public func _invoke_swift_closure_TestModule_10TestModule6PersonC_6PersonC(_ boxPtr: UnsafeMutableRawPointer, _ param0: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { #if arch(wasm32) - let closure = Unmanaged<_BridgeJSTypedClosureBox<(Theme) -> Bool>>.fromOpaque(boxPtr).takeUnretainedValue().closure - let result = closure(Theme.bridgeJSLiftParameter(param0Bytes, param0Length)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Person) -> Person>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Person.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -170,32 +170,32 @@ public func _invoke_swift_closure_TestModule_10TestModule5ThemeO_Sb(_ boxPtr: Un } #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule6PersonC_SS") -fileprivate func invoke_js_callback_TestModule_10TestModule6PersonC_SS(_ callback: Int32, _ param0: UnsafeMutableRawPointer) -> Int32 +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule9APIResultO_9APIResultO") +fileprivate func invoke_js_callback_TestModule_10TestModule9APIResultO_9APIResultO(_ callback: Int32, _ param0: Int32) -> Int32 #else -fileprivate func invoke_js_callback_TestModule_10TestModule6PersonC_SS(_ callback: Int32, _ param0: UnsafeMutableRawPointer) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModule9APIResultO_9APIResultO(_ callback: Int32, _ param0: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule6PersonC_SS") -fileprivate func make_swift_closure_TestModule_10TestModule6PersonC_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO") +fileprivate func make_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 #else -fileprivate func make_swift_closure_TestModule_10TestModule6PersonC_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { +fileprivate func make_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -private enum _BJS_Closure_10TestModule6PersonC_SS { - static func bridgeJSLift(_ callbackId: Int32) -> (Person) -> String { +private enum _BJS_Closure_10TestModule9APIResultO_9APIResultO { + static func bridgeJSLift(_ callbackId: Int32) -> (APIResult) -> APIResult { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) let callbackValue = callback.bridgeJSLowerParameter() - let param0Pointer = param0.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModule6PersonC_SS(callbackValue, param0Pointer) - return String.bridgeJSLiftReturn(ret) + let param0CaseId = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModule9APIResultO_9APIResultO(callbackValue, param0CaseId) + return APIResult.bridgeJSLiftReturn(ret) #else fatalError("Only available on WebAssembly") #endif @@ -203,10 +203,10 @@ private enum _BJS_Closure_10TestModule6PersonC_SS { } } -extension JSTypedClosure where Signature == (Person) -> String { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Person) -> String) { +extension JSTypedClosure where Signature == (APIResult) -> APIResult { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (APIResult) -> APIResult) { self.init( - makeClosure: make_swift_closure_TestModule_10TestModule6PersonC_SS, + makeClosure: make_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO, body: body, fileID: fileID, line: line @@ -214,12 +214,12 @@ extension JSTypedClosure where Signature == (Person) -> String { } } -@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule6PersonC_SS") -@_cdecl("invoke_swift_closure_TestModule_10TestModule6PersonC_SS") -public func _invoke_swift_closure_TestModule_10TestModule6PersonC_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0: UnsafeMutableRawPointer) -> Void { +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO") +@_cdecl("invoke_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO") +public func _invoke_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { #if arch(wasm32) - let closure = Unmanaged<_BridgeJSTypedClosureBox<(Person) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure - let result = closure(Person.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(APIResult) -> APIResult>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(APIResult.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -227,32 +227,32 @@ public func _invoke_swift_closure_TestModule_10TestModule6PersonC_SS(_ boxPtr: U } #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule9APIResultO_SS") -fileprivate func invoke_js_callback_TestModule_10TestModule9APIResultO_SS(_ callback: Int32, _ param0: Int32) -> Int32 +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule9DirectionO_9DirectionO") +fileprivate func invoke_js_callback_TestModule_10TestModule9DirectionO_9DirectionO(_ callback: Int32, _ param0: Int32) -> Int32 #else -fileprivate func invoke_js_callback_TestModule_10TestModule9APIResultO_SS(_ callback: Int32, _ param0: Int32) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModule9DirectionO_9DirectionO(_ callback: Int32, _ param0: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule9APIResultO_SS") -fileprivate func make_swift_closure_TestModule_10TestModule9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO") +fileprivate func make_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 #else -fileprivate func make_swift_closure_TestModule_10TestModule9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { +fileprivate func make_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -private enum _BJS_Closure_10TestModule9APIResultO_SS { - static func bridgeJSLift(_ callbackId: Int32) -> (APIResult) -> String { +private enum _BJS_Closure_10TestModule9DirectionO_9DirectionO { + static func bridgeJSLift(_ callbackId: Int32) -> (Direction) -> Direction { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) let callbackValue = callback.bridgeJSLowerParameter() - let param0CaseId = param0.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModule9APIResultO_SS(callbackValue, param0CaseId) - return String.bridgeJSLiftReturn(ret) + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModule9DirectionO_9DirectionO(callbackValue, param0Value) + return Direction.bridgeJSLiftReturn(ret) #else fatalError("Only available on WebAssembly") #endif @@ -260,10 +260,10 @@ private enum _BJS_Closure_10TestModule9APIResultO_SS { } } -extension JSTypedClosure where Signature == (APIResult) -> String { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (APIResult) -> String) { +extension JSTypedClosure where Signature == (Direction) -> Direction { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Direction) -> Direction) { self.init( - makeClosure: make_swift_closure_TestModule_10TestModule9APIResultO_SS, + makeClosure: make_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO, body: body, fileID: fileID, line: line @@ -271,12 +271,12 @@ extension JSTypedClosure where Signature == (APIResult) -> String { } } -@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule9APIResultO_SS") -@_cdecl("invoke_swift_closure_TestModule_10TestModule9APIResultO_SS") -public func _invoke_swift_closure_TestModule_10TestModule9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO") +@_cdecl("invoke_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO") +public func _invoke_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { #if arch(wasm32) - let closure = Unmanaged<_BridgeJSTypedClosureBox<(APIResult) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure - let result = closure(APIResult.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Direction) -> Direction>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Direction.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -284,31 +284,31 @@ public func _invoke_swift_closure_TestModule_10TestModule9APIResultO_SS(_ boxPtr } #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule9DirectionO_SS") -fileprivate func invoke_js_callback_TestModule_10TestModule9DirectionO_SS(_ callback: Int32, _ param0: Int32) -> Int32 +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSS_SS") +fileprivate func invoke_js_callback_TestModule_10TestModuleSS_SS(_ callback: Int32, _ param0: Int32) -> Int32 #else -fileprivate func invoke_js_callback_TestModule_10TestModule9DirectionO_SS(_ callback: Int32, _ param0: Int32) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModuleSS_SS(_ callback: Int32, _ param0: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule9DirectionO_SS") -fileprivate func make_swift_closure_TestModule_10TestModule9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSS_SS") +fileprivate func make_swift_closure_TestModule_10TestModuleSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 #else -fileprivate func make_swift_closure_TestModule_10TestModule9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { +fileprivate func make_swift_closure_TestModule_10TestModuleSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -private enum _BJS_Closure_10TestModule9DirectionO_SS { - static func bridgeJSLift(_ callbackId: Int32) -> (Direction) -> String { +private enum _BJS_Closure_10TestModuleSS_SS { + static func bridgeJSLift(_ callbackId: Int32) -> (String) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) let callbackValue = callback.bridgeJSLowerParameter() let param0Value = param0.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModule9DirectionO_SS(callbackValue, param0Value) + let ret = invoke_js_callback_TestModule_10TestModuleSS_SS(callbackValue, param0Value) return String.bridgeJSLiftReturn(ret) #else fatalError("Only available on WebAssembly") @@ -317,10 +317,10 @@ private enum _BJS_Closure_10TestModule9DirectionO_SS { } } -extension JSTypedClosure where Signature == (Direction) -> String { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Direction) -> String) { +extension JSTypedClosure where Signature == (String) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (String) -> String) { self.init( - makeClosure: make_swift_closure_TestModule_10TestModule9DirectionO_SS, + makeClosure: make_swift_closure_TestModule_10TestModuleSS_SS, body: body, fileID: fileID, line: line @@ -328,12 +328,12 @@ extension JSTypedClosure where Signature == (Direction) -> String { } } -@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule9DirectionO_SS") -@_cdecl("invoke_swift_closure_TestModule_10TestModule9DirectionO_SS") -public func _invoke_swift_closure_TestModule_10TestModule9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSS_SS") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSS_SS") +public func _invoke_swift_closure_TestModule_10TestModuleSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { #if arch(wasm32) - let closure = Unmanaged<_BridgeJSTypedClosureBox<(Direction) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure - let result = closure(Direction.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(String) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(String.bridgeJSLiftParameter(param0Bytes, param0Length)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -341,31 +341,31 @@ public func _invoke_swift_closure_TestModule_10TestModule9DirectionO_SS(_ boxPtr } #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule9DirectionO_Sb") -fileprivate func invoke_js_callback_TestModule_10TestModule9DirectionO_Sb(_ callback: Int32, _ param0: Int32) -> Int32 +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSb_Sb") +fileprivate func invoke_js_callback_TestModule_10TestModuleSb_Sb(_ callback: Int32, _ param0: Int32) -> Int32 #else -fileprivate func invoke_js_callback_TestModule_10TestModule9DirectionO_Sb(_ callback: Int32, _ param0: Int32) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModuleSb_Sb(_ callback: Int32, _ param0: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule9DirectionO_Sb") -fileprivate func make_swift_closure_TestModule_10TestModule9DirectionO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSb_Sb") +fileprivate func make_swift_closure_TestModule_10TestModuleSb_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 #else -fileprivate func make_swift_closure_TestModule_10TestModule9DirectionO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { +fileprivate func make_swift_closure_TestModule_10TestModuleSb_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -private enum _BJS_Closure_10TestModule9DirectionO_Sb { - static func bridgeJSLift(_ callbackId: Int32) -> (Direction) -> Bool { +private enum _BJS_Closure_10TestModuleSb_Sb { + static func bridgeJSLift(_ callbackId: Int32) -> (Bool) -> Bool { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) let callbackValue = callback.bridgeJSLowerParameter() let param0Value = param0.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModule9DirectionO_Sb(callbackValue, param0Value) + let ret = invoke_js_callback_TestModule_10TestModuleSb_Sb(callbackValue, param0Value) return Bool.bridgeJSLiftReturn(ret) #else fatalError("Only available on WebAssembly") @@ -374,10 +374,10 @@ private enum _BJS_Closure_10TestModule9DirectionO_Sb { } } -extension JSTypedClosure where Signature == (Direction) -> Bool { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Direction) -> Bool) { +extension JSTypedClosure where Signature == (Bool) -> Bool { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Bool) -> Bool) { self.init( - makeClosure: make_swift_closure_TestModule_10TestModule9DirectionO_Sb, + makeClosure: make_swift_closure_TestModule_10TestModuleSb_Sb, body: body, fileID: fileID, line: line @@ -385,12 +385,12 @@ extension JSTypedClosure where Signature == (Direction) -> Bool { } } -@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule9DirectionO_Sb") -@_cdecl("invoke_swift_closure_TestModule_10TestModule9DirectionO_Sb") -public func _invoke_swift_closure_TestModule_10TestModule9DirectionO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSb_Sb") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSb_Sb") +public func _invoke_swift_closure_TestModule_10TestModuleSb_Sb(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { #if arch(wasm32) - let closure = Unmanaged<_BridgeJSTypedClosureBox<(Direction) -> Bool>>.fromOpaque(boxPtr).takeUnretainedValue().closure - let result = closure(Direction.bridgeJSLiftParameter(param0)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Bool) -> Bool>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Bool.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -398,32 +398,32 @@ public func _invoke_swift_closure_TestModule_10TestModule9DirectionO_Sb(_ boxPtr } #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSS_SS") -fileprivate func invoke_js_callback_TestModule_10TestModuleSS_SS(_ callback: Int32, _ param0: Int32) -> Int32 +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSd_Sd") +fileprivate func invoke_js_callback_TestModule_10TestModuleSd_Sd(_ callback: Int32, _ param0: Float64) -> Float64 #else -fileprivate func invoke_js_callback_TestModule_10TestModuleSS_SS(_ callback: Int32, _ param0: Int32) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModuleSd_Sd(_ callback: Int32, _ param0: Float64) -> Float64 { fatalError("Only available on WebAssembly") } #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSS_SS") -fileprivate func make_swift_closure_TestModule_10TestModuleSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSd_Sd") +fileprivate func make_swift_closure_TestModule_10TestModuleSd_Sd(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 #else -fileprivate func make_swift_closure_TestModule_10TestModuleSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { +fileprivate func make_swift_closure_TestModule_10TestModuleSd_Sd(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -private enum _BJS_Closure_10TestModuleSS_SS { - static func bridgeJSLift(_ callbackId: Int32) -> (String) -> String { +private enum _BJS_Closure_10TestModuleSd_Sd { + static func bridgeJSLift(_ callbackId: Int32) -> (Double) -> Double { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) let callbackValue = callback.bridgeJSLowerParameter() let param0Value = param0.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModuleSS_SS(callbackValue, param0Value) - return String.bridgeJSLiftReturn(ret) + let ret = invoke_js_callback_TestModule_10TestModuleSd_Sd(callbackValue, param0Value) + return Double.bridgeJSLiftReturn(ret) #else fatalError("Only available on WebAssembly") #endif @@ -431,10 +431,10 @@ private enum _BJS_Closure_10TestModuleSS_SS { } } -extension JSTypedClosure where Signature == (String) -> String { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (String) -> String) { +extension JSTypedClosure where Signature == (Double) -> Double { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Double) -> Double) { self.init( - makeClosure: make_swift_closure_TestModule_10TestModuleSS_SS, + makeClosure: make_swift_closure_TestModule_10TestModuleSd_Sd, body: body, fileID: fileID, line: line @@ -442,12 +442,126 @@ extension JSTypedClosure where Signature == (String) -> String { } } -@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSS_SS") -@_cdecl("invoke_swift_closure_TestModule_10TestModuleSS_SS") -public func _invoke_swift_closure_TestModule_10TestModuleSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSd_Sd") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSd_Sd") +public func _invoke_swift_closure_TestModule_10TestModuleSd_Sd(_ boxPtr: UnsafeMutableRawPointer, _ param0: Float64) -> Float64 { #if arch(wasm32) - let closure = Unmanaged<_BridgeJSTypedClosureBox<(String) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure - let result = closure(String.bridgeJSLiftParameter(param0Bytes, param0Length)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Double) -> Double>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Double.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSf_Sf") +fileprivate func invoke_js_callback_TestModule_10TestModuleSf_Sf(_ callback: Int32, _ param0: Float32) -> Float32 +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSf_Sf(_ callback: Int32, _ param0: Float32) -> Float32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSf_Sf") +fileprivate func make_swift_closure_TestModule_10TestModuleSf_Sf(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSf_Sf(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSf_Sf { + static func bridgeJSLift(_ callbackId: Int32) -> (Float) -> Float { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModuleSf_Sf(callbackValue, param0Value) + return Float.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Float) -> Float { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Float) -> Float) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSf_Sf, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSf_Sf") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSf_Sf") +public func _invoke_swift_closure_TestModule_10TestModuleSf_Sf(_ boxPtr: UnsafeMutableRawPointer, _ param0: Float32) -> Float32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Float) -> Float>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Float.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSi_Si") +fileprivate func invoke_js_callback_TestModule_10TestModuleSi_Si(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSi_Si(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSi_Si") +fileprivate func make_swift_closure_TestModule_10TestModuleSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSi_Si { + static func bridgeJSLift(_ callbackId: Int32) -> (Int) -> Int { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModuleSi_Si(callbackValue, param0Value) + return Int.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Int) -> Int { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Int) -> Int) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSi_Si, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSi_Si") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSi_Si") +public func _invoke_swift_closure_TestModule_10TestModuleSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Int) -> Int>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Int.bridgeJSLiftParameter(param0)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -455,32 +569,32 @@ public func _invoke_swift_closure_TestModule_10TestModuleSS_SS(_ boxPtr: UnsafeM } #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq5ThemeO_SS") -fileprivate func invoke_js_callback_TestModule_10TestModuleSq5ThemeO_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO") +fileprivate func invoke_js_callback_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Void #else -fileprivate func invoke_js_callback_TestModule_10TestModuleSq5ThemeO_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq5ThemeO_SS") -fileprivate func make_swift_closure_TestModule_10TestModuleSq5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO") +fileprivate func make_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 #else -fileprivate func make_swift_closure_TestModule_10TestModuleSq5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { +fileprivate func make_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -private enum _BJS_Closure_10TestModuleSq5ThemeO_SS { - static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { +private enum _BJS_Closure_10TestModuleSq10HttpStatusO_Sq10HttpStatusO { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) let callbackValue = callback.bridgeJSLowerParameter() let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModuleSq5ThemeO_SS(callbackValue, param0IsSome, param0Value) - return String.bridgeJSLiftReturn(ret) + invoke_js_callback_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(callbackValue, param0IsSome, param0Value) + return Optional.bridgeJSLiftReturnFromSideChannel() #else fatalError("Only available on WebAssembly") #endif @@ -488,10 +602,10 @@ private enum _BJS_Closure_10TestModuleSq5ThemeO_SS { } } -extension JSTypedClosure where Signature == (Optional) -> String { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { self.init( - makeClosure: make_swift_closure_TestModule_10TestModuleSq5ThemeO_SS, + makeClosure: make_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO, body: body, fileID: fileID, line: line @@ -499,12 +613,12 @@ extension JSTypedClosure where Signature == (Optional) -> String { } } -@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_SS") -@_cdecl("invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_SS") -public func _invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO") +public func _invoke_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { #if arch(wasm32) - let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure - let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Bytes, param0Length)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -512,34 +626,32 @@ public func _invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_SS(_ boxPtr: } #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS") -fileprivate func invoke_js_callback_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Pointer: UnsafeMutableRawPointer, _ param1IsSome: Int32, _ param1Value: Int32, _ param2IsSome: Int32, _ param2Value: Float64) -> Int32 +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO") +fileprivate func invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Void #else -fileprivate func invoke_js_callback_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Pointer: UnsafeMutableRawPointer, _ param1IsSome: Int32, _ param1Value: Int32, _ param2IsSome: Int32, _ param2Value: Float64) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS") -fileprivate func make_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO") +fileprivate func make_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 #else -fileprivate func make_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { +fileprivate func make_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -private enum _BJS_Closure_10TestModuleSq6PersonCSqSSSqSd_SS { - static func bridgeJSLift(_ callbackId: Int32) -> (Optional, Optional, Optional) -> String { +private enum _BJS_Closure_10TestModuleSq5ThemeO_Sq5ThemeO { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { let callback = JSObject.bridgeJSLiftParameter(callbackId) - return { [callback] param0, param1, param2 in + return { [callback] param0 in #if arch(wasm32) let callbackValue = callback.bridgeJSLowerParameter() - let (param0IsSome, param0Pointer) = param0.bridgeJSLowerParameter() - let (param1IsSome, param1Value) = param1.bridgeJSLowerParameter() - let (param2IsSome, param2Value) = param2.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS(callbackValue, param0IsSome, param0Pointer, param1IsSome, param1Value, param2IsSome, param2Value) - return String.bridgeJSLiftReturn(ret) + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(callbackValue, param0IsSome, param0Value) + return Optional.bridgeJSLiftReturnFromSideChannel() #else fatalError("Only available on WebAssembly") #endif @@ -547,10 +659,10 @@ private enum _BJS_Closure_10TestModuleSq6PersonCSqSSSqSd_SS { } } -extension JSTypedClosure where Signature == (Optional, Optional, Optional) -> String { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional, Optional, Optional) -> String) { +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { self.init( - makeClosure: make_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS, + makeClosure: make_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO, body: body, fileID: fileID, line: line @@ -558,12 +670,12 @@ extension JSTypedClosure where Signature == (Optional, Optional, } } -@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS") -@_cdecl("invoke_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS") -public func _invoke_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: UnsafeMutableRawPointer, _ param1IsSome: Int32, _ param1Bytes: Int32, _ param1Length: Int32, _ param2IsSome: Int32, _ param2Value: Float64) -> Void { +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO") +public func _invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { #if arch(wasm32) - let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional, Optional, Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure - let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value), Optional.bridgeJSLiftParameter(param1IsSome, param1Bytes, param1Length), Optional.bridgeJSLiftParameter(param2IsSome, param2Value)) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Bytes, param0Length)) return result.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -571,32 +683,32 @@ public func _invoke_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS(_ } #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq6PersonC_SS") -fileprivate func invoke_js_callback_TestModule_10TestModuleSq6PersonC_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Pointer: UnsafeMutableRawPointer) -> Int32 +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC") +fileprivate func invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC(_ callback: Int32, _ param0IsSome: Int32, _ param0Pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer #else -fileprivate func invoke_js_callback_TestModule_10TestModuleSq6PersonC_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Pointer: UnsafeMutableRawPointer) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC(_ callback: Int32, _ param0IsSome: Int32, _ param0Pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { fatalError("Only available on WebAssembly") } #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq6PersonC_SS") -fileprivate func make_swift_closure_TestModule_10TestModuleSq6PersonC_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC") +fileprivate func make_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 #else -fileprivate func make_swift_closure_TestModule_10TestModuleSq6PersonC_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { +fileprivate func make_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -private enum _BJS_Closure_10TestModuleSq6PersonC_SS { - static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { +private enum _BJS_Closure_10TestModuleSq6PersonC_Sq6PersonC { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) let callbackValue = callback.bridgeJSLowerParameter() let (param0IsSome, param0Pointer) = param0.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModuleSq6PersonC_SS(callbackValue, param0IsSome, param0Pointer) - return String.bridgeJSLiftReturn(ret) + let ret = invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC(callbackValue, param0IsSome, param0Pointer) + return Optional.bridgeJSLiftReturn(ret) #else fatalError("Only available on WebAssembly") #endif @@ -604,10 +716,10 @@ private enum _BJS_Closure_10TestModuleSq6PersonC_SS { } } -extension JSTypedClosure where Signature == (Optional) -> String { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { self.init( - makeClosure: make_swift_closure_TestModule_10TestModuleSq6PersonC_SS, + makeClosure: make_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC, body: body, fileID: fileID, line: line @@ -615,11 +727,11 @@ extension JSTypedClosure where Signature == (Optional) -> String { } } -@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq6PersonC_SS") -@_cdecl("invoke_swift_closure_TestModule_10TestModuleSq6PersonC_SS") -public func _invoke_swift_closure_TestModule_10TestModuleSq6PersonC_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: UnsafeMutableRawPointer) -> Void { +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC") +public func _invoke_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) return result.bridgeJSLowerReturn() #else @@ -628,32 +740,32 @@ public func _invoke_swift_closure_TestModule_10TestModuleSq6PersonC_SS(_ boxPtr: } #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq9APIResultO_SS") -fileprivate func invoke_js_callback_TestModule_10TestModuleSq9APIResultO_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Int32 +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO") +fileprivate func invoke_js_callback_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(_ callback: Int32, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Int32 #else -fileprivate func invoke_js_callback_TestModule_10TestModuleSq9APIResultO_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(_ callback: Int32, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq9APIResultO_SS") -fileprivate func make_swift_closure_TestModule_10TestModuleSq9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO") +fileprivate func make_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 #else -fileprivate func make_swift_closure_TestModule_10TestModuleSq9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { +fileprivate func make_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -private enum _BJS_Closure_10TestModuleSq9APIResultO_SS { - static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { +private enum _BJS_Closure_10TestModuleSq9APIResultO_Sq9APIResultO { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) let callbackValue = callback.bridgeJSLowerParameter() let (param0IsSome, param0CaseId) = param0.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModuleSq9APIResultO_SS(callbackValue, param0IsSome, param0CaseId) - return String.bridgeJSLiftReturn(ret) + let ret = invoke_js_callback_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(callbackValue, param0IsSome, param0CaseId) + return Optional.bridgeJSLiftReturn(ret) #else fatalError("Only available on WebAssembly") #endif @@ -661,10 +773,10 @@ private enum _BJS_Closure_10TestModuleSq9APIResultO_SS { } } -extension JSTypedClosure where Signature == (Optional) -> String { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { self.init( - makeClosure: make_swift_closure_TestModule_10TestModuleSq9APIResultO_SS, + makeClosure: make_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO, body: body, fileID: fileID, line: line @@ -672,11 +784,11 @@ extension JSTypedClosure where Signature == (Optional) -> String { } } -@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_SS") -@_cdecl("invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_SS") -public func _invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Void { +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO") +public func _invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Void { #if arch(wasm32) - let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0CaseId)) return result.bridgeJSLowerReturn() #else @@ -685,32 +797,32 @@ public func _invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_SS(_ boxP } #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq9DirectionO_SS") -fileprivate func invoke_js_callback_TestModule_10TestModuleSq9DirectionO_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO") +fileprivate func invoke_js_callback_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 #else -fileprivate func invoke_js_callback_TestModule_10TestModuleSq9DirectionO_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq9DirectionO_SS") -fileprivate func make_swift_closure_TestModule_10TestModuleSq9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO") +fileprivate func make_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 #else -fileprivate func make_swift_closure_TestModule_10TestModuleSq9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { +fileprivate func make_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -private enum _BJS_Closure_10TestModuleSq9DirectionO_SS { - static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { +private enum _BJS_Closure_10TestModuleSq9DirectionO_Sq9DirectionO { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) let callbackValue = callback.bridgeJSLowerParameter() let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModuleSq9DirectionO_SS(callbackValue, param0IsSome, param0Value) - return String.bridgeJSLiftReturn(ret) + let ret = invoke_js_callback_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(callbackValue, param0IsSome, param0Value) + return Optional.bridgeJSLiftReturn(ret) #else fatalError("Only available on WebAssembly") #endif @@ -718,10 +830,10 @@ private enum _BJS_Closure_10TestModuleSq9DirectionO_SS { } } -extension JSTypedClosure where Signature == (Optional) -> String { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { self.init( - makeClosure: make_swift_closure_TestModule_10TestModuleSq9DirectionO_SS, + makeClosure: make_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO, body: body, fileID: fileID, line: line @@ -729,11 +841,11 @@ extension JSTypedClosure where Signature == (Optional) -> String { } } -@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_SS") -@_cdecl("invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_SS") -public func _invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO") +public func _invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { #if arch(wasm32) - let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) return result.bridgeJSLowerReturn() #else @@ -741,6 +853,291 @@ public func _invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_SS(_ boxP #endif } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSqSS_SqSS") +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSS_SqSS(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Void +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSS_SqSS(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSqSS_SqSS") +fileprivate func make_swift_closure_TestModule_10TestModuleSqSS_SqSS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSqSS_SqSS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSqSS_SqSS { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + invoke_js_callback_TestModule_10TestModuleSqSS_SqSS(callbackValue, param0IsSome, param0Value) + return Optional.bridgeJSLiftReturnFromSideChannel() + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSqSS_SqSS, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSqSS_SqSS") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSqSS_SqSS") +public func _invoke_swift_closure_TestModule_10TestModuleSqSS_SqSS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Bytes, param0Length)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSqSb_SqSb") +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSb_SqSb(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSb_SqSb(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSqSb_SqSb") +fileprivate func make_swift_closure_TestModule_10TestModuleSqSb_SqSb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSqSb_SqSb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSqSb_SqSb { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModuleSqSb_SqSb(callbackValue, param0IsSome, param0Value) + return Optional.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSqSb_SqSb, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSqSb_SqSb") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSqSb_SqSb") +public func _invoke_swift_closure_TestModule_10TestModuleSqSb_SqSb(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSqSd_SqSd") +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSd_SqSd(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Float64) -> Void +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSd_SqSd(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSqSd_SqSd") +fileprivate func make_swift_closure_TestModule_10TestModuleSqSd_SqSd(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSqSd_SqSd(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSqSd_SqSd { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + invoke_js_callback_TestModule_10TestModuleSqSd_SqSd(callbackValue, param0IsSome, param0Value) + return Optional.bridgeJSLiftReturnFromSideChannel() + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSqSd_SqSd, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSqSd_SqSd") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSqSd_SqSd") +public func _invoke_swift_closure_TestModule_10TestModuleSqSd_SqSd(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Float64) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSqSf_SqSf") +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSf_SqSf(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Float32) -> Void +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSf_SqSf(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Float32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSqSf_SqSf") +fileprivate func make_swift_closure_TestModule_10TestModuleSqSf_SqSf(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSqSf_SqSf(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSqSf_SqSf { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + invoke_js_callback_TestModule_10TestModuleSqSf_SqSf(callbackValue, param0IsSome, param0Value) + return Optional.bridgeJSLiftReturnFromSideChannel() + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSqSf_SqSf, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSqSf_SqSf") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSqSf_SqSf") +public func _invoke_swift_closure_TestModule_10TestModuleSqSf_SqSf(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Float32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSqSi_SqSi") +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSi_SqSi(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Void +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSi_SqSi(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSqSi_SqSi") +fileprivate func make_swift_closure_TestModule_10TestModuleSqSi_SqSi(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSqSi_SqSi(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSqSi_SqSi { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + invoke_js_callback_TestModule_10TestModuleSqSi_SqSi(callbackValue, param0IsSome, param0Value) + return Optional.bridgeJSLiftReturnFromSideChannel() + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSqSi_SqSi, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSqSi_SqSi") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSqSi_SqSi") +public func _invoke_swift_closure_TestModule_10TestModuleSqSi_SqSi(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + extension Direction: _BridgedSwiftCaseEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue @@ -867,235 +1264,279 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } } -@_expose(wasm, "bjs_Person_init") -@_cdecl("bjs_Person_init") -public func _bjs_Person_init(_ nameBytes: Int32, _ nameLength: Int32) -> UnsafeMutableRawPointer { +@_expose(wasm, "bjs_roundtripString") +@_cdecl("bjs_roundtripString") +public func _bjs_roundtripString(_ stringClosure: Int32) -> Int32 { #if arch(wasm32) - let ret = Person(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) - return ret.bridgeJSLowerReturn() + let ret = roundtripString(_: _BJS_Closure_10TestModuleSS_SS.bridgeJSLift(stringClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_Person_deinit") -@_cdecl("bjs_Person_deinit") -public func _bjs_Person_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { +@_expose(wasm, "bjs_roundtripInt") +@_cdecl("bjs_roundtripInt") +public func _bjs_roundtripInt(_ intClosure: Int32) -> Int32 { #if arch(wasm32) - Unmanaged.fromOpaque(pointer).release() + let ret = roundtripInt(_: _BJS_Closure_10TestModuleSi_Si.bridgeJSLift(intClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -extension Person: ConvertibleToJSValue, _BridgedSwiftHeapObject { - public var jsValue: JSValue { - return .object(JSObject(id: UInt32(bitPattern: _bjs_Person_wrap(Unmanaged.passRetained(self).toOpaque())))) - } +@_expose(wasm, "bjs_roundtripBool") +@_cdecl("bjs_roundtripBool") +public func _bjs_roundtripBool(_ boolClosure: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripBool(_: _BJS_Closure_10TestModuleSb_Sb.bridgeJSLift(boolClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif } -#if arch(wasm32) -@_extern(wasm, module: "TestModule", name: "bjs_Person_wrap") -fileprivate func _bjs_Person_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 -#else -fileprivate func _bjs_Person_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { +@_expose(wasm, "bjs_roundtripFloat") +@_cdecl("bjs_roundtripFloat") +public func _bjs_roundtripFloat(_ floatClosure: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripFloat(_: _BJS_Closure_10TestModuleSf_Sf.bridgeJSLift(floatClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else fatalError("Only available on WebAssembly") + #endif } -#endif -@_expose(wasm, "bjs_TestProcessor_init") -@_cdecl("bjs_TestProcessor_init") -public func _bjs_TestProcessor_init(_ transform: Int32) -> UnsafeMutableRawPointer { +@_expose(wasm, "bjs_roundtripDouble") +@_cdecl("bjs_roundtripDouble") +public func _bjs_roundtripDouble(_ doubleClosure: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor(transform: _BJS_Closure_10TestModuleSS_SS.bridgeJSLift(transform)) - return ret.bridgeJSLowerReturn() + let ret = roundtripDouble(_: _BJS_Closure_10TestModuleSd_Sd.bridgeJSLift(doubleClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_getTransform") -@_cdecl("bjs_TestProcessor_getTransform") -public func _bjs_TestProcessor_getTransform(_ _self: UnsafeMutableRawPointer) -> Int32 { +@_expose(wasm, "bjs_roundtripOptionalString") +@_cdecl("bjs_roundtripOptionalString") +public func _bjs_roundtripOptionalString(_ stringClosure: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).getTransform() + let ret = roundtripOptionalString(_: _BJS_Closure_10TestModuleSqSS_SqSS.bridgeJSLift(stringClosure)) return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_processWithCustom") -@_cdecl("bjs_TestProcessor_processWithCustom") -public func _bjs_TestProcessor_processWithCustom(_ _self: UnsafeMutableRawPointer, _ textBytes: Int32, _ textLength: Int32, _ customTransform: Int32) -> Void { +@_expose(wasm, "bjs_roundtripOptionalInt") +@_cdecl("bjs_roundtripOptionalInt") +public func _bjs_roundtripOptionalInt(_ intClosure: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).processWithCustom(_: String.bridgeJSLiftParameter(textBytes, textLength), customTransform: _BJS_Closure_10TestModuleSS_SS.bridgeJSLift(customTransform)) - return ret.bridgeJSLowerReturn() + let ret = roundtripOptionalInt(_: _BJS_Closure_10TestModuleSqSi_SqSi.bridgeJSLift(intClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_printTogether") -@_cdecl("bjs_TestProcessor_printTogether") -public func _bjs_TestProcessor_printTogether(_ _self: UnsafeMutableRawPointer, _ person: UnsafeMutableRawPointer, _ nameBytes: Int32, _ nameLength: Int32, _ ratio: Float64, _ customTransform: Int32) -> Void { +@_expose(wasm, "bjs_roundtripOptionalBool") +@_cdecl("bjs_roundtripOptionalBool") +public func _bjs_roundtripOptionalBool(_ boolClosure: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).printTogether(person: Person.bridgeJSLiftParameter(person), name: String.bridgeJSLiftParameter(nameBytes, nameLength), ratio: Double.bridgeJSLiftParameter(ratio), customTransform: _BJS_Closure_10TestModuleSq6PersonCSqSSSqSd_SS.bridgeJSLift(customTransform)) - return ret.bridgeJSLowerReturn() + let ret = roundtripOptionalBool(_: _BJS_Closure_10TestModuleSqSb_SqSb.bridgeJSLift(boolClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_roundtrip") -@_cdecl("bjs_TestProcessor_roundtrip") -public func _bjs_TestProcessor_roundtrip(_ _self: UnsafeMutableRawPointer, _ personClosure: Int32) -> Int32 { +@_expose(wasm, "bjs_roundtripOptionalFloat") +@_cdecl("bjs_roundtripOptionalFloat") +public func _bjs_roundtripOptionalFloat(_ floatClosure: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).roundtrip(_: _BJS_Closure_10TestModule6PersonC_SS.bridgeJSLift(personClosure)) + let ret = roundtripOptionalFloat(_: _BJS_Closure_10TestModuleSqSf_SqSf.bridgeJSLift(floatClosure)) return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_roundtripOptional") -@_cdecl("bjs_TestProcessor_roundtripOptional") -public func _bjs_TestProcessor_roundtripOptional(_ _self: UnsafeMutableRawPointer, _ personClosure: Int32) -> Int32 { +@_expose(wasm, "bjs_roundtripOptionalDouble") +@_cdecl("bjs_roundtripOptionalDouble") +public func _bjs_roundtripOptionalDouble(_ doubleClosure: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).roundtripOptional(_: _BJS_Closure_10TestModuleSq6PersonC_SS.bridgeJSLift(personClosure)) + let ret = roundtripOptionalDouble(_: _BJS_Closure_10TestModuleSqSd_SqSd.bridgeJSLift(doubleClosure)) return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_processDirection") -@_cdecl("bjs_TestProcessor_processDirection") -public func _bjs_TestProcessor_processDirection(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Void { +@_expose(wasm, "bjs_roundtripPerson") +@_cdecl("bjs_roundtripPerson") +public func _bjs_roundtripPerson(_ personClosure: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).processDirection(_: _BJS_Closure_10TestModule9DirectionO_SS.bridgeJSLift(callback)) - return ret.bridgeJSLowerReturn() + let ret = roundtripPerson(_: _BJS_Closure_10TestModule6PersonC_6PersonC.bridgeJSLift(personClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_processTheme") -@_cdecl("bjs_TestProcessor_processTheme") -public func _bjs_TestProcessor_processTheme(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Void { +@_expose(wasm, "bjs_roundtripOptionalPerson") +@_cdecl("bjs_roundtripOptionalPerson") +public func _bjs_roundtripOptionalPerson(_ personClosure: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).processTheme(_: _BJS_Closure_10TestModule5ThemeO_SS.bridgeJSLift(callback)) - return ret.bridgeJSLowerReturn() + let ret = roundtripOptionalPerson(_: _BJS_Closure_10TestModuleSq6PersonC_Sq6PersonC.bridgeJSLift(personClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_processHttpStatus") -@_cdecl("bjs_TestProcessor_processHttpStatus") -public func _bjs_TestProcessor_processHttpStatus(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Int32 { +@_expose(wasm, "bjs_roundtripDirection") +@_cdecl("bjs_roundtripDirection") +public func _bjs_roundtripDirection(_ callback: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).processHttpStatus(_: _BJS_Closure_10TestModule10HttpStatusO_Si.bridgeJSLift(callback)) - return ret.bridgeJSLowerReturn() + let ret = roundtripDirection(_: _BJS_Closure_10TestModule9DirectionO_9DirectionO.bridgeJSLift(callback)) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_processAPIResult") -@_cdecl("bjs_TestProcessor_processAPIResult") -public func _bjs_TestProcessor_processAPIResult(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Void { +@_expose(wasm, "bjs_roundtripTheme") +@_cdecl("bjs_roundtripTheme") +public func _bjs_roundtripTheme(_ callback: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).processAPIResult(_: _BJS_Closure_10TestModule9APIResultO_SS.bridgeJSLift(callback)) - return ret.bridgeJSLowerReturn() + let ret = roundtripTheme(_: _BJS_Closure_10TestModule5ThemeO_5ThemeO.bridgeJSLift(callback)) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_makeDirectionChecker") -@_cdecl("bjs_TestProcessor_makeDirectionChecker") -public func _bjs_TestProcessor_makeDirectionChecker(_ _self: UnsafeMutableRawPointer) -> Int32 { +@_expose(wasm, "bjs_roundtripHttpStatus") +@_cdecl("bjs_roundtripHttpStatus") +public func _bjs_roundtripHttpStatus(_ callback: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).makeDirectionChecker() + let ret = roundtripHttpStatus(_: _BJS_Closure_10TestModule10HttpStatusO_10HttpStatusO.bridgeJSLift(callback)) return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_makeThemeValidator") -@_cdecl("bjs_TestProcessor_makeThemeValidator") -public func _bjs_TestProcessor_makeThemeValidator(_ _self: UnsafeMutableRawPointer) -> Int32 { +@_expose(wasm, "bjs_roundtripAPIResult") +@_cdecl("bjs_roundtripAPIResult") +public func _bjs_roundtripAPIResult(_ callback: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).makeThemeValidator() + let ret = roundtripAPIResult(_: _BJS_Closure_10TestModule9APIResultO_9APIResultO.bridgeJSLift(callback)) return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_makeStatusCodeExtractor") -@_cdecl("bjs_TestProcessor_makeStatusCodeExtractor") -public func _bjs_TestProcessor_makeStatusCodeExtractor(_ _self: UnsafeMutableRawPointer) -> Int32 { +@_expose(wasm, "bjs_roundtripOptionalDirection") +@_cdecl("bjs_roundtripOptionalDirection") +public func _bjs_roundtripOptionalDirection(_ callback: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).makeStatusCodeExtractor() + let ret = roundtripOptionalDirection(_: _BJS_Closure_10TestModuleSq9DirectionO_Sq9DirectionO.bridgeJSLift(callback)) return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_makeAPIResultHandler") -@_cdecl("bjs_TestProcessor_makeAPIResultHandler") -public func _bjs_TestProcessor_makeAPIResultHandler(_ _self: UnsafeMutableRawPointer) -> Int32 { +@_expose(wasm, "bjs_roundtripOptionalTheme") +@_cdecl("bjs_roundtripOptionalTheme") +public func _bjs_roundtripOptionalTheme(_ callback: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).makeAPIResultHandler() + let ret = roundtripOptionalTheme(_: _BJS_Closure_10TestModuleSq5ThemeO_Sq5ThemeO.bridgeJSLift(callback)) return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_processOptionalDirection") -@_cdecl("bjs_TestProcessor_processOptionalDirection") -public func _bjs_TestProcessor_processOptionalDirection(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Void { +@_expose(wasm, "bjs_roundtripOptionalHttpStatus") +@_cdecl("bjs_roundtripOptionalHttpStatus") +public func _bjs_roundtripOptionalHttpStatus(_ callback: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).processOptionalDirection(_: _BJS_Closure_10TestModuleSq9DirectionO_SS.bridgeJSLift(callback)) - return ret.bridgeJSLowerReturn() + let ret = roundtripOptionalHttpStatus(_: _BJS_Closure_10TestModuleSq10HttpStatusO_Sq10HttpStatusO.bridgeJSLift(callback)) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_processOptionalTheme") -@_cdecl("bjs_TestProcessor_processOptionalTheme") -public func _bjs_TestProcessor_processOptionalTheme(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Void { +@_expose(wasm, "bjs_roundtripOptionalAPIResult") +@_cdecl("bjs_roundtripOptionalAPIResult") +public func _bjs_roundtripOptionalAPIResult(_ callback: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).processOptionalTheme(_: _BJS_Closure_10TestModuleSq5ThemeO_SS.bridgeJSLift(callback)) - return ret.bridgeJSLowerReturn() + let ret = roundtripOptionalAPIResult(_: _BJS_Closure_10TestModuleSq9APIResultO_Sq9APIResultO.bridgeJSLift(callback)) + return JSTypedClosure(ret).bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_processOptionalAPIResult") -@_cdecl("bjs_TestProcessor_processOptionalAPIResult") -public func _bjs_TestProcessor_processOptionalAPIResult(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Void { +@_expose(wasm, "bjs_roundtripOptionalDirection") +@_cdecl("bjs_roundtripOptionalDirection") +public func _bjs_roundtripOptionalDirection(_ callback: Int32) -> Int32 { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).processOptionalAPIResult(_: _BJS_Closure_10TestModuleSq9APIResultO_SS.bridgeJSLift(callback)) + let ret = roundtripOptionalDirection(_: _BJS_Closure_10TestModuleSq9DirectionO_Sq9DirectionO.bridgeJSLift(callback)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Person_init") +@_cdecl("bjs_Person_init") +public func _bjs_Person_init(_ nameBytes: Int32, _ nameLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Person(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_TestProcessor_makeOptionalDirectionFormatter") -@_cdecl("bjs_TestProcessor_makeOptionalDirectionFormatter") -public func _bjs_TestProcessor_makeOptionalDirectionFormatter(_ _self: UnsafeMutableRawPointer) -> Int32 { +@_expose(wasm, "bjs_Person_deinit") +@_cdecl("bjs_Person_deinit") +public func _bjs_Person_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let ret = TestProcessor.bridgeJSLiftParameter(_self).makeOptionalDirectionFormatter() - return JSTypedClosure(ret).bridgeJSLowerReturn() + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Person: ConvertibleToJSValue, _BridgedSwiftHeapObject { + public var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Person_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Person_wrap") +fileprivate func _bjs_Person_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Person_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_TestProcessor_init") +@_cdecl("bjs_TestProcessor_init") +public func _bjs_TestProcessor_init(_ transform: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = TestProcessor(transform: _BJS_Closure_10TestModuleSS_SS.bridgeJSLift(transform)) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.d.ts index 942b18269..ccc95eb3b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.d.ts @@ -59,23 +59,6 @@ export interface SwiftHeapObject { export interface Person extends SwiftHeapObject { } export interface TestProcessor extends SwiftHeapObject { - getTransform(): (arg0: string) => string; - processWithCustom(text: string, customTransform: (arg0: string) => string): string; - printTogether(person: Person, name: string, ratio: number, customTransform: (arg0: Person | null, arg1: string | null, arg2: number | null) => string): string; - roundtrip(personClosure: (arg0: Person) => string): (arg0: Person) => string; - roundtripOptional(personClosure: (arg0: Person | null) => string): (arg0: Person | null) => string; - processDirection(callback: (arg0: DirectionTag) => string): string; - processTheme(callback: (arg0: ThemeTag) => string): string; - processHttpStatus(callback: (arg0: HttpStatusTag) => number): number; - processAPIResult(callback: (arg0: APIResultTag) => string): string; - makeDirectionChecker(): (arg0: DirectionTag) => boolean; - makeThemeValidator(): (arg0: ThemeTag) => boolean; - makeStatusCodeExtractor(): (arg0: HttpStatusTag) => number; - makeAPIResultHandler(): (arg0: APIResultTag) => string; - processOptionalDirection(callback: (arg0: DirectionTag | null) => string): string; - processOptionalTheme(callback: (arg0: ThemeTag | null) => string): string; - processOptionalAPIResult(callback: (arg0: APIResultTag | null) => string): string; - makeOptionalDirectionFormatter(): (arg0: DirectionTag | null) => string; } export type Exports = { Person: { @@ -84,6 +67,27 @@ export type Exports = { TestProcessor: { new(transform: (arg0: string) => string): TestProcessor; } + roundtripString(stringClosure: (arg0: string) => string): (arg0: string) => string; + roundtripInt(intClosure: (arg0: number) => number): (arg0: number) => number; + roundtripBool(boolClosure: (arg0: boolean) => boolean): (arg0: boolean) => boolean; + roundtripFloat(floatClosure: (arg0: number) => number): (arg0: number) => number; + roundtripDouble(doubleClosure: (arg0: number) => number): (arg0: number) => number; + roundtripOptionalString(stringClosure: (arg0: string | null) => string | null): (arg0: string | null) => string | null; + roundtripOptionalInt(intClosure: (arg0: number | null) => number | null): (arg0: number | null) => number | null; + roundtripOptionalBool(boolClosure: (arg0: boolean | null) => boolean | null): (arg0: boolean | null) => boolean | null; + roundtripOptionalFloat(floatClosure: (arg0: number | null) => number | null): (arg0: number | null) => number | null; + roundtripOptionalDouble(doubleClosure: (arg0: number | null) => number | null): (arg0: number | null) => number | null; + roundtripPerson(personClosure: (arg0: Person) => Person): (arg0: Person) => Person; + roundtripOptionalPerson(personClosure: (arg0: Person | null) => Person | null): (arg0: Person | null) => Person | null; + roundtripDirection(callback: (arg0: DirectionTag) => DirectionTag): (arg0: DirectionTag) => DirectionTag; + roundtripTheme(callback: (arg0: ThemeTag) => ThemeTag): (arg0: ThemeTag) => ThemeTag; + roundtripHttpStatus(callback: (arg0: HttpStatusTag) => HttpStatusTag): (arg0: HttpStatusTag) => HttpStatusTag; + roundtripAPIResult(callback: (arg0: APIResultTag) => APIResultTag): (arg0: APIResultTag) => APIResultTag; + roundtripOptionalDirection(callback: (arg0: DirectionTag | null) => DirectionTag | null): (arg0: DirectionTag | null) => DirectionTag | null; + roundtripOptionalTheme(callback: (arg0: ThemeTag | null) => ThemeTag | null): (arg0: ThemeTag | null) => ThemeTag | null; + roundtripOptionalHttpStatus(callback: (arg0: HttpStatusTag | null) => HttpStatusTag | null): (arg0: HttpStatusTag | null) => HttpStatusTag | null; + roundtripOptionalAPIResult(callback: (arg0: APIResultTag | null) => APIResultTag | null): (arg0: APIResultTag | null) => APIResultTag | null; + roundtripOptionalDirection(callback: (arg0: DirectionTag | null) => DirectionTag | null): (arg0: DirectionTag | null) => DirectionTag | null; Direction: DirectionObject Theme: ThemeObject HttpStatus: HttpStatusObject diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js index 38c248cae..09f9aee59 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js @@ -329,7 +329,7 @@ export async function createInstantiator(options, swift) { func.__unregister(); } - bjs["invoke_js_callback_TestModule_10TestModule10HttpStatusO_Si"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModule10HttpStatusO_10HttpStatusO"] = function(callbackId, param0Id) { try { const callback = swift.memory.getObject(callbackId); let param0 = param0Id; @@ -340,9 +340,9 @@ export async function createInstantiator(options, swift) { return 0; } }; - bjs["make_swift_closure_TestModule_10TestModule10HttpStatusO_Si"] = function(boxPtr, file, line) { - const lower_closure_TestModule_10TestModule10HttpStatusO_Si = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule10HttpStatusO_Si(boxPtr, param0); + bjs["make_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO = function(param0) { + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); @@ -351,19 +351,16 @@ export async function createInstantiator(options, swift) { } return invokeResult | 0; }; - return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule10HttpStatusO_Si); + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO); } - bjs["invoke_js_callback_TestModule_10TestModule5ThemeO_SS"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO"] = function(callbackId, param0Id) { try { const callback = swift.memory.getObject(callbackId); const param0IdObject = swift.memory.getObject(param0Id); swift.memory.release(param0Id); let param0 = String(param0IdObject); const result = callback(param0); - if (typeof result !== "string") { - throw new TypeError("Callback must return a string"); - } tmpRetBytes = textEncoder.encode(result); return tmpRetBytes.length; } catch (error) { @@ -372,11 +369,11 @@ export async function createInstantiator(options, swift) { return 0; } }; - bjs["make_swift_closure_TestModule_10TestModule5ThemeO_SS"] = function(boxPtr, file, line) { - const lower_closure_TestModule_10TestModule5ThemeO_SS = function(param0) { + bjs["make_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule5ThemeO_5ThemeO = function(param0) { const param0Bytes = textEncoder.encode(param0); const param0Id = swift.memory.retain(param0Bytes); - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule5ThemeO_SS(boxPtr, param0Id, param0Bytes.length); + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO(boxPtr, param0Id, param0Bytes.length); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); @@ -388,109 +385,95 @@ export async function createInstantiator(options, swift) { tmpRetString = undefined; return ret; }; - return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule5ThemeO_SS); + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule5ThemeO_5ThemeO); } - bjs["invoke_js_callback_TestModule_10TestModule5ThemeO_Sb"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModule6PersonC_6PersonC"] = function(callbackId, param0Id) { try { const callback = swift.memory.getObject(callbackId); - const param0IdObject = swift.memory.getObject(param0Id); - swift.memory.release(param0Id); - let param0 = String(param0IdObject); + let param0 = _exports['Person'].__construct(param0Id); const result = callback(param0); - return result ? 1 : 0; + return result.pointer; } catch (error) { setException?.(error); return 0; } }; - bjs["make_swift_closure_TestModule_10TestModule5ThemeO_Sb"] = function(boxPtr, file, line) { - const lower_closure_TestModule_10TestModule5ThemeO_Sb = function(param0) { - const param0Bytes = textEncoder.encode(param0); - const param0Id = swift.memory.retain(param0Bytes); - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule5ThemeO_Sb(boxPtr, param0Id, param0Bytes.length); + bjs["make_swift_closure_TestModule_10TestModule6PersonC_6PersonC"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule6PersonC_6PersonC = function(param0) { + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule6PersonC_6PersonC(boxPtr, param0.pointer); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - return invokeResult !== 0; + const resultPtr = invokeResult; + return _exports['Person'].__construct(resultPtr); }; - return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule5ThemeO_Sb); + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule6PersonC_6PersonC); } - bjs["invoke_js_callback_TestModule_10TestModule6PersonC_SS"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModule9APIResultO_9APIResultO"] = function(callbackId, param0Id) { try { const callback = swift.memory.getObject(callbackId); - let param0 = _exports['Person'].__construct(param0Id); + let param0 = enumHelpers.APIResult.lift(param0Id); const result = callback(param0); - if (typeof result !== "string") { - throw new TypeError("Callback must return a string"); - } - tmpRetBytes = textEncoder.encode(result); - return tmpRetBytes.length; + const { caseId: caseId, cleanup: cleanup } = enumHelpers.APIResult.lower(result); + return caseId; } catch (error) { setException?.(error); - tmpRetBytes = new Uint8Array(0); - return 0; + return; } }; - bjs["make_swift_closure_TestModule_10TestModule6PersonC_SS"] = function(boxPtr, file, line) { - const lower_closure_TestModule_10TestModule6PersonC_SS = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule6PersonC_SS(boxPtr, param0.pointer); + bjs["make_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule9APIResultO_9APIResultO = function(param0) { + const { caseId: param0CaseId, cleanup: param0Cleanup } = enumHelpers.APIResult.lower(param0); + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO(boxPtr, param0CaseId); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - const resultLen = invokeResult; - const ret = tmpRetString; - tmpRetString = undefined; - return ret; + invokeResult; + const result = enumHelpers.APIResult.lift(tagStack.pop()); + return result; }; - return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule6PersonC_SS); + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule9APIResultO_9APIResultO); } - bjs["invoke_js_callback_TestModule_10TestModule9APIResultO_SS"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModule9DirectionO_9DirectionO"] = function(callbackId, param0Id) { try { const callback = swift.memory.getObject(callbackId); - let param0 = enumHelpers.APIResult.lift(param0Id); + let param0 = param0Id; const result = callback(param0); - if (typeof result !== "string") { - throw new TypeError("Callback must return a string"); - } - tmpRetBytes = textEncoder.encode(result); - return tmpRetBytes.length; + return result | 0; } catch (error) { setException?.(error); - tmpRetBytes = new Uint8Array(0); return 0; } }; - bjs["make_swift_closure_TestModule_10TestModule9APIResultO_SS"] = function(boxPtr, file, line) { - const lower_closure_TestModule_10TestModule9APIResultO_SS = function(param0) { - const { caseId: param0CaseId, cleanup: param0Cleanup } = enumHelpers.APIResult.lower(param0); - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule9APIResultO_SS(boxPtr, param0CaseId); + bjs["make_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule9DirectionO_9DirectionO = function(param0) { + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - const resultLen = invokeResult; - const ret = tmpRetString; - tmpRetString = undefined; - return ret; + return invokeResult | 0; }; - return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule9APIResultO_SS); + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule9DirectionO_9DirectionO); } - bjs["invoke_js_callback_TestModule_10TestModule9DirectionO_SS"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModuleSS_SS"] = function(callbackId, param0Id) { try { const callback = swift.memory.getObject(callbackId); - let param0 = param0Id; + const param0IdObject = swift.memory.getObject(param0Id); + swift.memory.release(param0Id); + let param0 = String(param0IdObject); const result = callback(param0); if (typeof result !== "string") { throw new TypeError("Callback must return a string"); @@ -503,9 +486,11 @@ export async function createInstantiator(options, swift) { return 0; } }; - bjs["make_swift_closure_TestModule_10TestModule9DirectionO_SS"] = function(boxPtr, file, line) { - const lower_closure_TestModule_10TestModule9DirectionO_SS = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule9DirectionO_SS(boxPtr, param0); + bjs["make_swift_closure_TestModule_10TestModuleSS_SS"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSS_SS = function(param0) { + const param0Bytes = textEncoder.encode(param0); + const param0Id = swift.memory.retain(param0Bytes); + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSS_SS(boxPtr, param0Id, param0Bytes.length); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); @@ -517,13 +502,13 @@ export async function createInstantiator(options, swift) { tmpRetString = undefined; return ret; }; - return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule9DirectionO_SS); + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSS_SS); } - bjs["invoke_js_callback_TestModule_10TestModule9DirectionO_Sb"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModuleSb_Sb"] = function(callbackId, param0Id) { try { const callback = swift.memory.getObject(callbackId); - let param0 = param0Id; + let param0 = param0Id !== 0; const result = callback(param0); return result ? 1 : 0; } catch (error) { @@ -531,9 +516,9 @@ export async function createInstantiator(options, swift) { return 0; } }; - bjs["make_swift_closure_TestModule_10TestModule9DirectionO_Sb"] = function(boxPtr, file, line) { - const lower_closure_TestModule_10TestModule9DirectionO_Sb = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule9DirectionO_Sb(boxPtr, param0); + bjs["make_swift_closure_TestModule_10TestModuleSb_Sb"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSb_Sb = function(param0) { + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSb_Sb(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); @@ -542,47 +527,120 @@ export async function createInstantiator(options, swift) { } return invokeResult !== 0; }; - return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule9DirectionO_Sb); + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSb_Sb); } - bjs["invoke_js_callback_TestModule_10TestModuleSS_SS"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModuleSd_Sd"] = function(callbackId, param0Id) { try { const callback = swift.memory.getObject(callbackId); - const param0IdObject = swift.memory.getObject(param0Id); - swift.memory.release(param0Id); - let param0 = String(param0IdObject); + let param0 = param0Id; const result = callback(param0); - if (typeof result !== "string") { - throw new TypeError("Callback must return a string"); + return result; + } catch (error) { + setException?.(error); + return 0.0; + } + }; + bjs["make_swift_closure_TestModule_10TestModuleSd_Sd"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSd_Sd = function(param0) { + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSd_Sd(boxPtr, param0); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; } - tmpRetBytes = textEncoder.encode(result); - return tmpRetBytes.length; + return invokeResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSd_Sd); + } + + bjs["invoke_js_callback_TestModule_10TestModuleSf_Sf"] = function(callbackId, param0Id) { + try { + const callback = swift.memory.getObject(callbackId); + let param0 = param0Id; + const result = callback(param0); + return Math.fround(result); + } catch (error) { + setException?.(error); + return 0.0; + } + }; + bjs["make_swift_closure_TestModule_10TestModuleSf_Sf"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSf_Sf = function(param0) { + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSf_Sf(boxPtr, param0); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return invokeResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSf_Sf); + } + + bjs["invoke_js_callback_TestModule_10TestModuleSi_Si"] = function(callbackId, param0Id) { + try { + const callback = swift.memory.getObject(callbackId); + let param0 = param0Id; + const result = callback(param0); + return result | 0; } catch (error) { setException?.(error); - tmpRetBytes = new Uint8Array(0); return 0; } }; - bjs["make_swift_closure_TestModule_10TestModuleSS_SS"] = function(boxPtr, file, line) { - const lower_closure_TestModule_10TestModuleSS_SS = function(param0) { - const param0Bytes = textEncoder.encode(param0); - const param0Id = swift.memory.retain(param0Bytes); - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSS_SS(boxPtr, param0Id, param0Bytes.length); + bjs["make_swift_closure_TestModule_10TestModuleSi_Si"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSi_Si = function(param0) { + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSi_Si(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - const resultLen = invokeResult; - const ret = tmpRetString; - tmpRetString = undefined; - return ret; + return invokeResult | 0; }; - return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSS_SS); + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSi_Si); + } + + bjs["invoke_js_callback_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO"] = function(callbackId, param0IsSome, param0Value) { + try { + const callback = swift.memory.getObject(callbackId); + let param0; + if (param0IsSome) { + param0 = param0Value; + } else { + param0 = null; + } + const result = callback(param0); + tmpRetOptionalInt = result; + return; + } catch (error) { + setException?.(error); + return; + } + }; + bjs["make_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO = function(param0) { + const isSome = param0 != null; + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(boxPtr, +isSome, isSome ? param0 : 0); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + invokeResult; + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO); } - bjs["invoke_js_callback_TestModule_10TestModuleSq5ThemeO_SS"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO"] = function(callbackId, param0IsSome, param0Value) { try { const callback = swift.memory.getObject(callbackId); let param0; @@ -594,41 +652,37 @@ export async function createInstantiator(options, swift) { param0 = null; } const result = callback(param0); - if (typeof result !== "string") { - throw new TypeError("Callback must return a string"); - } - tmpRetBytes = textEncoder.encode(result); - return tmpRetBytes.length; + tmpRetString = result; + return; } catch (error) { setException?.(error); - tmpRetBytes = new Uint8Array(0); - return 0; + return; } }; - bjs["make_swift_closure_TestModule_10TestModuleSq5ThemeO_SS"] = function(boxPtr, file, line) { - const lower_closure_TestModule_10TestModuleSq5ThemeO_SS = function(param0) { + bjs["make_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO = function(param0) { const isSome = param0 != null; let param0Id, param0Bytes; if (isSome) { param0Bytes = textEncoder.encode(param0); param0Id = swift.memory.retain(param0Bytes); } - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_SS(boxPtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(boxPtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - const resultLen = invokeResult; - const ret = tmpRetString; + invokeResult; + const optResult = tmpRetString; tmpRetString = undefined; - return ret; + return optResult; }; - return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq5ThemeO_SS); + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO); } - bjs["invoke_js_callback_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS"] = function(callbackId, param0IsSome, param0Value, param1IsSome, param1Value, param2IsSome, param2Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC"] = function(callbackId, param0IsSome, param0Value) { try { const callback = swift.memory.getObject(callbackId); let param0; @@ -637,142 +691,197 @@ export async function createInstantiator(options, swift) { } else { param0 = null; } - let param1; - if (param1IsSome) { - const param1Object = swift.memory.getObject(param1Value); - swift.memory.release(param1Value); - param1 = String(param1Object); - } else { - param1 = null; + const result = callback(param0); + return result ? result.pointer : 0; + } catch (error) { + setException?.(error); + return 0; + } + }; + bjs["make_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC = function(param0) { + const isSome = param0 != null; + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC(boxPtr, +isSome, isSome ? param0.pointer : 0); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; } - let param2; - if (param2IsSome) { - param2 = param2Value; + invokeResult; + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + const optResult = pointer === null ? null : _exports['Person'].__construct(pointer); + return optResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC); + } + + bjs["invoke_js_callback_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO"] = function(callbackId, param0IsSome, param0Value) { + try { + const callback = swift.memory.getObject(callbackId); + let param0; + if (param0IsSome) { + param0 = enumHelpers.APIResult.lift(param0Value); } else { - param2 = null; + param0 = null; } - const result = callback(param0, param1, param2); - if (typeof result !== "string") { - throw new TypeError("Callback must return a string"); + const result = callback(param0); + if (result) { + const { caseId: caseId, cleanup: cleanup } = enumHelpers.APIResult.lower(result); + tmpRetOptionalInt = caseId; + } else { + tmpRetOptionalInt = null; } - tmpRetBytes = textEncoder.encode(result); - return tmpRetBytes.length; + return; } catch (error) { setException?.(error); - tmpRetBytes = new Uint8Array(0); - return 0; + return; } }; - bjs["make_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS"] = function(boxPtr, file, line) { - const lower_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS = function(param0, param1, param2) { + bjs["make_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO = function(param0) { const isSome = param0 != null; - const isSome1 = param1 != null; - let param1Id, param1Bytes; - if (isSome1) { - param1Bytes = textEncoder.encode(param1); - param1Id = swift.memory.retain(param1Bytes); - } - const isSome2 = param2 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS(boxPtr, +isSome, isSome ? param0.pointer : 0, +isSome1, isSome1 ? param1Id : 0, isSome1 ? param1Bytes.length : 0, +isSome2, isSome2 ? param2 : 0); + let param0CaseId, param0Cleanup; + if (isSome) { + const enumResult = enumHelpers.APIResult.lower(param0); + param0CaseId = enumResult.caseId; + param0Cleanup = enumResult.cleanup; + } + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(boxPtr, +isSome, isSome ? param0CaseId : 0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - const resultLen = invokeResult; - const ret = tmpRetString; - tmpRetString = undefined; - return ret; + invokeResult; + const tag = tagStack.pop(); + const isNull = (tag === -1); + let optResult; + if (isNull) { + optResult = null; + } else { + optResult = enumHelpers.APIResult.lift(tag); + } + return optResult; }; - return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq6PersonCSqSSSqSd_SS); + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO); } - bjs["invoke_js_callback_TestModule_10TestModuleSq6PersonC_SS"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO"] = function(callbackId, param0IsSome, param0Value) { try { const callback = swift.memory.getObject(callbackId); let param0; if (param0IsSome) { - param0 = _exports['Person'].__construct(param0Value); + param0 = param0Value; } else { param0 = null; } const result = callback(param0); - if (typeof result !== "string") { - throw new TypeError("Callback must return a string"); - } - tmpRetBytes = textEncoder.encode(result); - return tmpRetBytes.length; + tmpRetOptionalInt = result; + return; } catch (error) { setException?.(error); - tmpRetBytes = new Uint8Array(0); - return 0; + return; } }; - bjs["make_swift_closure_TestModule_10TestModuleSq6PersonC_SS"] = function(boxPtr, file, line) { - const lower_closure_TestModule_10TestModuleSq6PersonC_SS = function(param0) { + bjs["make_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO = function(param0) { const isSome = param0 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq6PersonC_SS(boxPtr, +isSome, isSome ? param0.pointer : 0); + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(boxPtr, +isSome, isSome ? param0 : 0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - const resultLen = invokeResult; - const ret = tmpRetString; - tmpRetString = undefined; - return ret; + invokeResult; + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; }; - return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq6PersonC_SS); + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO); } - bjs["invoke_js_callback_TestModule_10TestModuleSq9APIResultO_SS"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSqSS_SqSS"] = function(callbackId, param0IsSome, param0Value) { try { const callback = swift.memory.getObject(callbackId); let param0; if (param0IsSome) { - param0 = enumHelpers.APIResult.lift(param0Value); + const param0Object = swift.memory.getObject(param0Value); + swift.memory.release(param0Value); + param0 = String(param0Object); } else { param0 = null; } const result = callback(param0); - if (typeof result !== "string") { - throw new TypeError("Callback must return a string"); - } - tmpRetBytes = textEncoder.encode(result); - return tmpRetBytes.length; + tmpRetString = result; + return; } catch (error) { setException?.(error); - tmpRetBytes = new Uint8Array(0); - return 0; + return; } }; - bjs["make_swift_closure_TestModule_10TestModuleSq9APIResultO_SS"] = function(boxPtr, file, line) { - const lower_closure_TestModule_10TestModuleSq9APIResultO_SS = function(param0) { + bjs["make_swift_closure_TestModule_10TestModuleSqSS_SqSS"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSqSS_SqSS = function(param0) { const isSome = param0 != null; - let param0CaseId, param0Cleanup; + let param0Id, param0Bytes; if (isSome) { - const enumResult = enumHelpers.APIResult.lower(param0); - param0CaseId = enumResult.caseId; - param0Cleanup = enumResult.cleanup; + param0Bytes = textEncoder.encode(param0); + param0Id = swift.memory.retain(param0Bytes); } - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_SS(boxPtr, +isSome, isSome ? param0CaseId : 0); + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSS_SqSS(boxPtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - const resultLen = invokeResult; - const ret = tmpRetString; + invokeResult; + const optResult = tmpRetString; tmpRetString = undefined; - return ret; + return optResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSS_SqSS); + } + + bjs["invoke_js_callback_TestModule_10TestModuleSqSb_SqSb"] = function(callbackId, param0IsSome, param0Value) { + try { + const callback = swift.memory.getObject(callbackId); + let param0; + if (param0IsSome) { + param0 = param0Value !== 0; + } else { + param0 = null; + } + const result = callback(param0); + tmpRetOptionalBool = result; + return; + } catch (error) { + setException?.(error); + return; + } + }; + bjs["make_swift_closure_TestModule_10TestModuleSqSb_SqSb"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSqSb_SqSb = function(param0) { + const isSome = param0 != null; + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSb_SqSb(boxPtr, +isSome, isSome ? param0 : 0); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + invokeResult; + const optResult = tmpRetOptionalBool; + tmpRetOptionalBool = undefined; + return optResult; }; - return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq9APIResultO_SS); + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSb_SqSb); } - bjs["invoke_js_callback_TestModule_10TestModuleSq9DirectionO_SS"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSqSd_SqSd"] = function(callbackId, param0IsSome, param0Value) { try { const callback = swift.memory.getObject(callbackId); let param0; @@ -782,33 +891,99 @@ export async function createInstantiator(options, swift) { param0 = null; } const result = callback(param0); - if (typeof result !== "string") { - throw new TypeError("Callback must return a string"); + tmpRetOptionalDouble = result; + return; + } catch (error) { + setException?.(error); + return; + } + }; + bjs["make_swift_closure_TestModule_10TestModuleSqSd_SqSd"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSqSd_SqSd = function(param0) { + const isSome = param0 != null; + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSd_SqSd(boxPtr, +isSome, isSome ? param0 : 0); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; } - tmpRetBytes = textEncoder.encode(result); - return tmpRetBytes.length; + invokeResult; + const optResult = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + return optResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSd_SqSd); + } + + bjs["invoke_js_callback_TestModule_10TestModuleSqSf_SqSf"] = function(callbackId, param0IsSome, param0Value) { + try { + const callback = swift.memory.getObject(callbackId); + let param0; + if (param0IsSome) { + param0 = Math.fround(param0Value); + } else { + param0 = null; + } + const result = callback(param0); + tmpRetOptionalFloat = result; + return; } catch (error) { setException?.(error); - tmpRetBytes = new Uint8Array(0); - return 0; + return; } }; - bjs["make_swift_closure_TestModule_10TestModuleSq9DirectionO_SS"] = function(boxPtr, file, line) { - const lower_closure_TestModule_10TestModuleSq9DirectionO_SS = function(param0) { + bjs["make_swift_closure_TestModule_10TestModuleSqSf_SqSf"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSqSf_SqSf = function(param0) { const isSome = param0 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_SS(boxPtr, +isSome, isSome ? param0 : 0); + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSf_SqSf(boxPtr, +isSome, isSome ? param0 : 0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - const resultLen = invokeResult; - const ret = tmpRetString; - tmpRetString = undefined; - return ret; + invokeResult; + const optResult = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; + return optResult; }; - return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq9DirectionO_SS); + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSf_SqSf); + } + + bjs["invoke_js_callback_TestModule_10TestModuleSqSi_SqSi"] = function(callbackId, param0IsSome, param0Value) { + try { + const callback = swift.memory.getObject(callbackId); + let param0; + if (param0IsSome) { + param0 = param0Value | 0; + } else { + param0 = null; + } + const result = callback(param0); + tmpRetOptionalInt = result; + return; + } catch (error) { + setException?.(error); + return; + } + }; + bjs["make_swift_closure_TestModule_10TestModuleSqSi_SqSi"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSqSi_SqSi = function(param0) { + const isSome = param0 != null; + const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSi_SqSi(boxPtr, +isSome, isSome ? param0 : 0); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + invokeResult; + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSi_SqSi); } // Wrapper functions for module: TestModule if (!importObject["TestModule"]) { @@ -876,114 +1051,118 @@ export async function createInstantiator(options, swift) { const ret = instance.exports.bjs_TestProcessor_init(callbackId); return TestProcessor.__construct(ret); } - getTransform() { - const ret = instance.exports.bjs_TestProcessor_getTransform(this.pointer); + } + const APIResultHelpers = __bjs_createAPIResultValuesHelpers()(); + enumHelpers.APIResult = APIResultHelpers; + + const exports = { + Person, + TestProcessor, + roundtripString: function bjs_roundtripString(stringClosure) { + const callbackId = swift.memory.retain(stringClosure); + const ret = instance.exports.bjs_roundtripString(callbackId); return swift.memory.getObject(ret); - } - processWithCustom(text, customTransform) { - const textBytes = textEncoder.encode(text); - const textId = swift.memory.retain(textBytes); - const callbackId = swift.memory.retain(customTransform); - instance.exports.bjs_TestProcessor_processWithCustom(this.pointer, textId, textBytes.length, callbackId); - const ret = tmpRetString; - tmpRetString = undefined; - swift.memory.release(textId); - return ret; - } - printTogether(person, name, ratio, customTransform) { - const nameBytes = textEncoder.encode(name); - const nameId = swift.memory.retain(nameBytes); - const callbackId = swift.memory.retain(customTransform); - instance.exports.bjs_TestProcessor_printTogether(this.pointer, person.pointer, nameId, nameBytes.length, ratio, callbackId); - const ret = tmpRetString; - tmpRetString = undefined; - swift.memory.release(nameId); - return ret; - } - roundtrip(personClosure) { + }, + roundtripInt: function bjs_roundtripInt(intClosure) { + const callbackId = swift.memory.retain(intClosure); + const ret = instance.exports.bjs_roundtripInt(callbackId); + return swift.memory.getObject(ret); + }, + roundtripBool: function bjs_roundtripBool(boolClosure) { + const callbackId = swift.memory.retain(boolClosure); + const ret = instance.exports.bjs_roundtripBool(callbackId); + return swift.memory.getObject(ret); + }, + roundtripFloat: function bjs_roundtripFloat(floatClosure) { + const callbackId = swift.memory.retain(floatClosure); + const ret = instance.exports.bjs_roundtripFloat(callbackId); + return swift.memory.getObject(ret); + }, + roundtripDouble: function bjs_roundtripDouble(doubleClosure) { + const callbackId = swift.memory.retain(doubleClosure); + const ret = instance.exports.bjs_roundtripDouble(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalString: function bjs_roundtripOptionalString(stringClosure) { + const callbackId = swift.memory.retain(stringClosure); + const ret = instance.exports.bjs_roundtripOptionalString(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalInt: function bjs_roundtripOptionalInt(intClosure) { + const callbackId = swift.memory.retain(intClosure); + const ret = instance.exports.bjs_roundtripOptionalInt(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalBool: function bjs_roundtripOptionalBool(boolClosure) { + const callbackId = swift.memory.retain(boolClosure); + const ret = instance.exports.bjs_roundtripOptionalBool(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalFloat: function bjs_roundtripOptionalFloat(floatClosure) { + const callbackId = swift.memory.retain(floatClosure); + const ret = instance.exports.bjs_roundtripOptionalFloat(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalDouble: function bjs_roundtripOptionalDouble(doubleClosure) { + const callbackId = swift.memory.retain(doubleClosure); + const ret = instance.exports.bjs_roundtripOptionalDouble(callbackId); + return swift.memory.getObject(ret); + }, + roundtripPerson: function bjs_roundtripPerson(personClosure) { const callbackId = swift.memory.retain(personClosure); - const ret = instance.exports.bjs_TestProcessor_roundtrip(this.pointer, callbackId); + const ret = instance.exports.bjs_roundtripPerson(callbackId); return swift.memory.getObject(ret); - } - roundtripOptional(personClosure) { + }, + roundtripOptionalPerson: function bjs_roundtripOptionalPerson(personClosure) { const callbackId = swift.memory.retain(personClosure); - const ret = instance.exports.bjs_TestProcessor_roundtripOptional(this.pointer, callbackId); + const ret = instance.exports.bjs_roundtripOptionalPerson(callbackId); return swift.memory.getObject(ret); - } - processDirection(callback) { + }, + roundtripDirection: function bjs_roundtripDirection(callback) { const callbackId = swift.memory.retain(callback); - instance.exports.bjs_TestProcessor_processDirection(this.pointer, callbackId); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } - processTheme(callback) { - const callbackId = swift.memory.retain(callback); - instance.exports.bjs_TestProcessor_processTheme(this.pointer, callbackId); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } - processHttpStatus(callback) { + const ret = instance.exports.bjs_roundtripDirection(callbackId); + return swift.memory.getObject(ret); + }, + roundtripTheme: function bjs_roundtripTheme(callback) { const callbackId = swift.memory.retain(callback); - const ret = instance.exports.bjs_TestProcessor_processHttpStatus(this.pointer, callbackId); - return ret; - } - processAPIResult(callback) { + const ret = instance.exports.bjs_roundtripTheme(callbackId); + return swift.memory.getObject(ret); + }, + roundtripHttpStatus: function bjs_roundtripHttpStatus(callback) { const callbackId = swift.memory.retain(callback); - instance.exports.bjs_TestProcessor_processAPIResult(this.pointer, callbackId); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } - makeDirectionChecker() { - const ret = instance.exports.bjs_TestProcessor_makeDirectionChecker(this.pointer); + const ret = instance.exports.bjs_roundtripHttpStatus(callbackId); return swift.memory.getObject(ret); - } - makeThemeValidator() { - const ret = instance.exports.bjs_TestProcessor_makeThemeValidator(this.pointer); + }, + roundtripAPIResult: function bjs_roundtripAPIResult(callback) { + const callbackId = swift.memory.retain(callback); + const ret = instance.exports.bjs_roundtripAPIResult(callbackId); return swift.memory.getObject(ret); - } - makeStatusCodeExtractor() { - const ret = instance.exports.bjs_TestProcessor_makeStatusCodeExtractor(this.pointer); + }, + roundtripOptionalDirection: function bjs_roundtripOptionalDirection(callback) { + const callbackId = swift.memory.retain(callback); + const ret = instance.exports.bjs_roundtripOptionalDirection(callbackId); return swift.memory.getObject(ret); - } - makeAPIResultHandler() { - const ret = instance.exports.bjs_TestProcessor_makeAPIResultHandler(this.pointer); + }, + roundtripOptionalTheme: function bjs_roundtripOptionalTheme(callback) { + const callbackId = swift.memory.retain(callback); + const ret = instance.exports.bjs_roundtripOptionalTheme(callbackId); return swift.memory.getObject(ret); - } - processOptionalDirection(callback) { + }, + roundtripOptionalHttpStatus: function bjs_roundtripOptionalHttpStatus(callback) { const callbackId = swift.memory.retain(callback); - instance.exports.bjs_TestProcessor_processOptionalDirection(this.pointer, callbackId); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } - processOptionalTheme(callback) { + const ret = instance.exports.bjs_roundtripOptionalHttpStatus(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalAPIResult: function bjs_roundtripOptionalAPIResult(callback) { const callbackId = swift.memory.retain(callback); - instance.exports.bjs_TestProcessor_processOptionalTheme(this.pointer, callbackId); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } - processOptionalAPIResult(callback) { + const ret = instance.exports.bjs_roundtripOptionalAPIResult(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalDirection: function bjs_roundtripOptionalDirection(callback) { const callbackId = swift.memory.retain(callback); - instance.exports.bjs_TestProcessor_processOptionalAPIResult(this.pointer, callbackId); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } - makeOptionalDirectionFormatter() { - const ret = instance.exports.bjs_TestProcessor_makeOptionalDirectionFormatter(this.pointer); + const ret = instance.exports.bjs_roundtripOptionalDirection(callbackId); return swift.memory.getObject(ret); - } - } - const APIResultHelpers = __bjs_createAPIResultValuesHelpers()(); - enumHelpers.APIResult = APIResultHelpers; - - const exports = { - Person, - TestProcessor, + }, Direction: DirectionValues, Theme: ThemeValues, HttpStatus: HttpStatusValues, From d9adac0230dd96dfbb07d07bc14b0433e13718b5 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 9 Feb 2026 10:28:46 +0900 Subject: [PATCH 03/40] [NFC] Fix warnings (#603) * [NFC] BridgeJS: Fix unused variable warning in BridgeJSCommandPlugin.swift * [NFC] JavaScriptEventLoop: Fix warnings for undeclared SPI usage --- .../Sources/BridgeJSCommandPlugin/BridgeJSCommandPlugin.swift | 1 - .../JavaScriptEventLoop+ExecutorFactory.swift | 4 ++++ Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSCommandPlugin/BridgeJSCommandPlugin.swift b/Plugins/BridgeJS/Sources/BridgeJSCommandPlugin/BridgeJSCommandPlugin.swift index 3dce62578..a45a06188 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCommandPlugin/BridgeJSCommandPlugin.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCommandPlugin/BridgeJSCommandPlugin.swift @@ -98,7 +98,6 @@ extension BridgeJSCommandPlugin.Context { printStderr("Generating bridge code for \(target.name)...") let generatedDirectory = target.directoryURL.appending(path: "Generated") - let generatedJavaScriptDirectory = generatedDirectory.appending(path: "JavaScript") let bridgeDtsPath = target.directoryURL.appending(path: "bridge-js.d.ts") let tsconfigPath = context.package.directoryURL.appending(path: "tsconfig.json") diff --git a/Sources/JavaScriptEventLoop/JavaScriptEventLoop+ExecutorFactory.swift b/Sources/JavaScriptEventLoop/JavaScriptEventLoop+ExecutorFactory.swift index d31e03597..7de4cb74a 100644 --- a/Sources/JavaScriptEventLoop/JavaScriptEventLoop+ExecutorFactory.swift +++ b/Sources/JavaScriptEventLoop/JavaScriptEventLoop+ExecutorFactory.swift @@ -4,7 +4,11 @@ // See: https://github.com/swiftlang/swift/pull/80266 // See: https://forums.swift.org/t/pitch-2-custom-main-and-global-executors/78437 +#if compiler(>=6.3) @_spi(ExperimentalCustomExecutors) import _Concurrency +#else +import _Concurrency +#endif import _CJavaScriptKit #if compiler(>=6.3) diff --git a/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift b/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift index 4b4115602..aebc90d65 100644 --- a/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift +++ b/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift @@ -1,5 +1,9 @@ import JavaScriptKit +#if compiler(>=6.3) @_spi(ExperimentalCustomExecutors) import _Concurrency +#else +import _Concurrency +#endif import _CJavaScriptEventLoop import _CJavaScriptKit From f2bf525e0f5ce52f706c016aba815ac0f1857bfe Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 9 Feb 2026 10:36:49 +0900 Subject: [PATCH 04/40] BridgeJS: Support `@JS class` in imported function signatures (#601) --- .../Sources/BridgeJSCore/ImportTS.swift | 28 ++----------- .../Sources/BridgeJSLink/JSGlueGen.swift | 22 ++--------- .../Inputs/MacroSwift/SwiftClass.swift | 2 + .../BridgeJSCodegenTests/SwiftClass.json | 29 ++++++++++++++ .../BridgeJSCodegenTests/SwiftClass.swift | 20 +++++++++- .../BridgeJSLinkTests/Protocol.js | 2 +- .../BridgeJSLinkTests/SwiftClass.d.ts | 1 + .../BridgeJSLinkTests/SwiftClass.js | 11 ++++++ .../Generated/BridgeJS.swift | 18 +++++++++ .../Generated/JavaScript/BridgeJS.json | 39 +++++++++++++++++++ .../JavaScript/SwiftClassSupportTests.mjs | 10 +++++ .../SwiftClassSupportTests.swift | 13 +++++++ Tests/prelude.mjs | 2 + 13 files changed, 153 insertions(+), 44 deletions(-) create mode 100644 Tests/BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs create mode 100644 Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift index 0424d8ca0..08366abf3 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift @@ -957,18 +957,8 @@ extension BridgeType { return LoweringParameterInfo(loweredParameters: [("funcRef", .i32)]) case .unsafePointer: return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)]) - case .swiftHeapObject(let className): - switch context { - case .importTS: - throw BridgeJSCoreError( - """ - swiftHeapObject '\(className)' is not supported in TypeScript imports. - Swift classes can only be used in @JS protocols where Swift owns the instance. - """ - ) - case .exportSwift: - return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)]) - } + case .swiftHeapObject: + return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)]) case .swiftProtocol: throw BridgeJSCoreError("swiftProtocol is not supported in imported signatures") case .caseEnum: @@ -1038,18 +1028,8 @@ extension BridgeType { return LiftingReturnInfo(valueToLift: .i32) case .unsafePointer: return LiftingReturnInfo(valueToLift: .pointer) - case .swiftHeapObject(let className): - switch context { - case .importTS: - throw BridgeJSCoreError( - """ - swiftHeapObject '\(className)' cannot be returned from imported TypeScript functions. - JavaScript cannot create Swift heap objects. - """ - ) - case .exportSwift: - return LiftingReturnInfo(valueToLift: .pointer) - } + case .swiftHeapObject: + return LiftingReturnInfo(valueToLift: .pointer) case .swiftProtocol: throw BridgeJSCoreError("swiftProtocol is not supported in imported signatures") case .caseEnum: diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index dec77b3cb..68230e8d1 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -581,7 +581,7 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["pointer"], printCode: { arguments, scope, printer, cleanupCode in - return ["\(name).__construct(\(arguments[0]))"] + return ["_exports['\(name)'].__construct(\(arguments[0]))"] } ) } @@ -1985,14 +1985,7 @@ struct IntrinsicJSFragment: Sendable { case .jsValue: return .jsValueLiftParameter case .unsafePointer: return .identity case .swiftHeapObject(let name): - switch context { - case .importTS: - throw BridgeJSLinkError( - message: "swiftHeapObject '\(name)' can only be used in protocol exports, not in \(context)" - ) - case .exportSwift: - return .swiftHeapObjectLiftParameter(name) - } + return .swiftHeapObjectLiftParameter(name) case .swiftProtocol: return .jsObjectLiftParameter case .void: throw BridgeJSLinkError( @@ -2074,15 +2067,8 @@ struct IntrinsicJSFragment: Sendable { case .jsObject: return .jsObjectLowerReturn case .jsValue: return .jsValueLowerReturn(context: context) case .unsafePointer: return .identity - case .swiftHeapObject(let name): - switch context { - case .importTS: - throw BridgeJSLinkError( - message: "swiftHeapObject '\(name)' can only be used in protocol exports, not in \(context)" - ) - case .exportSwift: - return .swiftHeapObjectLowerReturn - } + case .swiftHeapObject: + return .swiftHeapObjectLowerReturn case .swiftProtocol: return .jsObjectLowerReturn case .void: return .void case .nullable(let wrappedType, let kind): diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClass.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClass.swift index 116b00878..aa520783a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClass.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClass.swift @@ -18,3 +18,5 @@ @JS public class PublicGreeter {} @JS package class PackageGreeter {} + +@JSFunction func jsRoundTripGreeter(greeter: Greeter) throws(JSException) -> Greeter diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.json index 9fe717651..d1bf42cff 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.json @@ -141,5 +141,34 @@ ] }, + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "jsRoundTripGreeter", + "parameters" : [ + { + "name" : "greeter", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "types" : [ + + ] + } + ] + }, "moduleName" : "TestModule" } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.swift index 216dfc684..581d6f1c0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.swift @@ -134,4 +134,22 @@ fileprivate func _bjs_PackageGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> fileprivate func _bjs_PackageGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { fatalError("Only available on WebAssembly") } -#endif \ No newline at end of file +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_jsRoundTripGreeter") +fileprivate func bjs_jsRoundTripGreeter(_ greeter: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer +#else +fileprivate func bjs_jsRoundTripGreeter(_ greeter: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripGreeter(_ greeter: Greeter) throws(JSException) -> Greeter { + let greeterPointer = greeter.bridgeJSLowerParameter() + let ret = bjs_jsRoundTripGreeter(greeterPointer) + if let error = _swift_js_take_exception() { + throw error + } + return Greeter.bridgeJSLiftReturn(ret) +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js index 57587d84a..00b9626e3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js @@ -513,7 +513,7 @@ export async function createInstantiator(options, swift) { } TestModule["bjs_MyViewControllerDelegate_onHelperUpdated"] = function bjs_MyViewControllerDelegate_onHelperUpdated(self, helper) { try { - swift.memory.getObject(self).onHelperUpdated(Helper.__construct(helper)); + swift.memory.getObject(self).onHelperUpdated(_exports['Helper'].__construct(helper)); } catch (error) { setException(error); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.d.ts index 8718463a9..d3461f8c1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.d.ts @@ -31,6 +31,7 @@ export type Exports = { takeGreeter(greeter: Greeter): void; } export type Imports = { + jsRoundTripGreeter(greeter: Greeter): Greeter; } export function createInstantiator(options: { imports: Imports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js index 6002d190f..eaa5d7720 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js @@ -38,6 +38,7 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; + const imports = options.getImports(importsContext); bjs["swift_js_return_string"] = function(ptr, len) { const bytes = new Uint8Array(memory.buffer, ptr, len); tmpRetString = textDecoder.decode(bytes); @@ -214,6 +215,16 @@ export async function createInstantiator(options, swift) { const obj = PublicGreeter.__construct(pointer); return swift.memory.retain(obj); }; + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_jsRoundTripGreeter"] = function bjs_jsRoundTripGreeter(greeter) { + try { + let ret = imports.jsRoundTripGreeter(_exports['Greeter'].__construct(greeter)); + return ret.pointer; + } catch (error) { + setException(error); + return 0 + } + } }, setInstance: (i) => { instance = i; diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index 163c9e479..1feb3eed6 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -10666,4 +10666,22 @@ func _$jsRoundTripOptionalStringUndefined(_ name: JSUndefinedOr) throws( throw error } return JSUndefinedOr.bridgeJSLiftReturnFromSideChannel() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_SwiftClassSupportImports_jsRoundTripGreeter_static") +fileprivate func bjs_SwiftClassSupportImports_jsRoundTripGreeter_static(_ greeter: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer +#else +fileprivate func bjs_SwiftClassSupportImports_jsRoundTripGreeter_static(_ greeter: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + fatalError("Only available on WebAssembly") +} +#endif + +func _$SwiftClassSupportImports_jsRoundTripGreeter(_ greeter: Greeter) throws(JSException) -> Greeter { + let greeterPointer = greeter.bridgeJSLowerParameter() + let ret = bjs_SwiftClassSupportImports_jsRoundTripGreeter_static(greeterPointer) + if let error = _swift_js_take_exception() { + throw error + } + return Greeter.bridgeJSLiftReturn(ret) } \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json index 23f47b03d..de7ab4a5d 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json @@ -15310,6 +15310,45 @@ "types" : [ ] + }, + { + "functions" : [ + + ], + "types" : [ + { + "getters" : [ + + ], + "methods" : [ + + ], + "name" : "SwiftClassSupportImports", + "setters" : [ + + ], + "staticMethods" : [ + { + "name" : "jsRoundTripGreeter", + "parameters" : [ + { + "name" : "greeter", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ] + } + ] } ] }, diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs new file mode 100644 index 000000000..fdb5d498d --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs @@ -0,0 +1,10 @@ +/** + * @returns {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Imports["SwiftClassSupportImports"]} + */ +export function getImports(importsContext) { + return { + jsRoundTripGreeter: (greeter) => { + return greeter; + }, + }; +} \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift b/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift new file mode 100644 index 000000000..3cee17554 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift @@ -0,0 +1,13 @@ +import XCTest +@_spi(Experimental) import JavaScriptKit + +@JSClass struct SwiftClassSupportImports { + @JSFunction static func jsRoundTripGreeter(_ greeter: Greeter) throws(JSException) -> Greeter +} + +final class SwiftClassSupportTests: XCTestCase { + func testRoundTripGreeter() throws { + let greeter = try SwiftClassSupportImports.jsRoundTripGreeter(Greeter(name: "Hello")) + XCTAssertEqual(greeter.name, "Hello") + } +} diff --git a/Tests/prelude.mjs b/Tests/prelude.mjs index 95573b34e..efb168a6d 100644 --- a/Tests/prelude.mjs +++ b/Tests/prelude.mjs @@ -6,6 +6,7 @@ import { import { ImportedFoo } from './BridgeJSRuntimeTests/JavaScript/Types.mjs'; import { runJsOptionalSupportTests } from './BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs'; import { getImports as getClosureSupportImports } from './BridgeJSRuntimeTests/JavaScript/ClosureSupportTests.mjs'; +import { getImports as getSwiftClassSupportImports } from './BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs'; /** @type {import('../.build/plugins/PackageToJS/outputs/PackageTests/test.d.ts').SetupOptionsFn} */ export async function setupOptions(options, context) { @@ -213,6 +214,7 @@ export async function setupOptions(options, context) { runJsOptionalSupportTests(exports); }, ClosureSupportImports: getClosureSupportImports(importsContext), + SwiftClassSupportImports: getSwiftClassSupportImports(importsContext), }; }, addToCoreImports(importObject, importsContext) { From 3a22f4d4d443e4f520c61c2a0460a699720df561 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 9 Feb 2026 10:57:19 +0900 Subject: [PATCH 05/40] BridgeJS: Add profiling instrumentation (#604) --- .../Sources/BridgeJSCore/ClosureCodegen.swift | 6 +- .../Sources/BridgeJSCore/ExportSwift.swift | 64 +++++----- .../Sources/BridgeJSCore/ImportTS.swift | 30 +++-- .../BridgeJS/Sources/BridgeJSCore/Misc.swift | 115 ++++++++++++++++++ .../Sources/BridgeJSTool/BridgeJSTool.swift | 102 ++++++++++------ 5 files changed, 236 insertions(+), 81 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift index 12e4a413c..3ec0418b3 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift @@ -328,7 +328,9 @@ public struct ClosureCodegen { decls.append(try renderClosureInvokeHandler(signature)) } - let format = BasicFormat() - return decls.map { $0.formatted(using: format).description }.joined(separator: "\n\n") + return withSpan("Format Closure Glue") { + let format = BasicFormat() + return decls.map { $0.formatted(using: format).description }.joined(separator: "\n\n") + } } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index acff21847..70ed8f8a8 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -47,45 +47,53 @@ public class ExportSwift { func renderSwiftGlue() throws -> String? { var decls: [DeclSyntax] = [] - let protocolCodegen = ProtocolCodegen() - for proto in skeleton.protocols { - decls.append(contentsOf: try protocolCodegen.renderProtocolWrapper(proto, moduleName: moduleName)) + try withSpan("Render Protocols") { [self] in + let protocolCodegen = ProtocolCodegen() + for proto in skeleton.protocols { + decls.append(contentsOf: try protocolCodegen.renderProtocolWrapper(proto, moduleName: moduleName)) + } } - let enumCodegen = EnumCodegen() - for enumDef in skeleton.enums { - if let enumHelpers = enumCodegen.renderEnumHelpers(enumDef) { - decls.append(enumHelpers) - } + try withSpan("Render Enums") { [self] in + let enumCodegen = EnumCodegen() + for enumDef in skeleton.enums { + if let enumHelpers = enumCodegen.renderEnumHelpers(enumDef) { + decls.append(enumHelpers) + } - for staticMethod in enumDef.staticMethods { - decls.append(try renderSingleExportedFunction(function: staticMethod)) - } + for staticMethod in enumDef.staticMethods { + decls.append(try renderSingleExportedFunction(function: staticMethod)) + } - for staticProperty in enumDef.staticProperties { - decls.append( - contentsOf: try renderSingleExportedProperty( - property: staticProperty, - context: .enumStatic(enumDef: enumDef) + for staticProperty in enumDef.staticProperties { + decls.append( + contentsOf: try renderSingleExportedProperty( + property: staticProperty, + context: .enumStatic(enumDef: enumDef) + ) ) - ) + } } } - let structCodegen = StructCodegen() - for structDef in skeleton.structs { - decls.append(contentsOf: structCodegen.renderStructHelpers(structDef)) - decls.append(contentsOf: try renderSingleExportedStruct(struct: structDef)) - } + try withSpan("Render Structs") { [self] in + let structCodegen = StructCodegen() + for structDef in skeleton.structs { + decls.append(contentsOf: structCodegen.renderStructHelpers(structDef)) + decls.append(contentsOf: try renderSingleExportedStruct(struct: structDef)) + } - for function in skeleton.functions { - decls.append(try renderSingleExportedFunction(function: function)) + for function in skeleton.functions { + decls.append(try renderSingleExportedFunction(function: function)) + } + for klass in skeleton.classes { + decls.append(contentsOf: try renderSingleExportedClass(klass: klass)) + } } - for klass in skeleton.classes { - decls.append(contentsOf: try renderSingleExportedClass(klass: klass)) + return withSpan("Format Export Glue") { + let format = BasicFormat() + return decls.map { $0.formatted(using: format).description }.joined(separator: "\n\n") } - let format = BasicFormat() - return decls.map { $0.formatted(using: format).description }.joined(separator: "\n\n") } class ExportedThunkBuilder { diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift index 08366abf3..d5cc945ee 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift @@ -32,17 +32,23 @@ public struct ImportTS { var decls: [DeclSyntax] = [] for skeleton in self.skeleton.children { - for getter in skeleton.globalGetters { - let getterDecls = try renderSwiftGlobalGetter(getter, topLevelDecls: &decls) - decls.append(contentsOf: getterDecls) + try withSpan("Render Global Getters") { + for getter in skeleton.globalGetters { + let getterDecls = try renderSwiftGlobalGetter(getter, topLevelDecls: &decls) + decls.append(contentsOf: getterDecls) + } } - for function in skeleton.functions { - let thunkDecls = try renderSwiftThunk(function, topLevelDecls: &decls) - decls.append(contentsOf: thunkDecls) + try withSpan("Render Functions") { + for function in skeleton.functions { + let thunkDecls = try renderSwiftThunk(function, topLevelDecls: &decls) + decls.append(contentsOf: thunkDecls) + } } - for type in skeleton.types { - let typeDecls = try renderSwiftType(type, topLevelDecls: &decls) - decls.append(contentsOf: typeDecls) + try withSpan("Render Types") { + for type in skeleton.types { + let typeDecls = try renderSwiftType(type, topLevelDecls: &decls) + decls.append(contentsOf: typeDecls) + } } } if decls.isEmpty { @@ -50,8 +56,10 @@ public struct ImportTS { return nil } - let format = BasicFormat() - return decls.map { $0.formatted(using: format).description }.joined(separator: "\n\n") + return withSpan("Format Import Glue") { + let format = BasicFormat() + return decls.map { $0.formatted(using: format).description }.joined(separator: "\n\n") + } } func renderSwiftGlobalGetter( diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift index e11bd4058..70dae3a82 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift @@ -1,3 +1,12 @@ +import class Foundation.FileHandle +import class Foundation.ProcessInfo +import func Foundation.open +import func Foundation.strerror +import var Foundation.errno +import var Foundation.O_WRONLY +import var Foundation.O_CREAT +import var Foundation.O_TRUNC + // MARK: - ProgressReporting public struct ProgressReporting { @@ -20,6 +29,112 @@ public struct ProgressReporting { } } +// MARK: - Profiling + +/// A simple time-profiler to emit `chrome://tracing` format +public final class Profiling { + nonisolated(unsafe) static var current: Profiling? + + let startTime: ContinuousClock.Instant + let clock = ContinuousClock() + let output: @Sendable (String) -> Void + var firstEntry = true + + init(output: @Sendable @escaping (String) -> Void) { + self.startTime = ContinuousClock.now + self.output = output + } + + public static func with(body: @escaping () throws -> Void) rethrows -> Void { + guard let outputPath = ProcessInfo.processInfo.environment["BRIDGE_JS_PROFILING"] else { + return try body() + } + let fd = open(outputPath, O_WRONLY | O_CREAT | O_TRUNC, 0o644) + guard fd >= 0 else { + let error = String(cString: strerror(errno)) + fatalError("Failed to open profiling output file \(outputPath): \(error)") + } + let output = FileHandle(fileDescriptor: fd, closeOnDealloc: true) + let profiling = Profiling(output: { output.write($0.data(using: .utf8) ?? Data()) }) + defer { + profiling.output("]\n") + } + Profiling.current = profiling + defer { + Profiling.current = nil + } + return try body() + } + + private func formatTimestamp(instant: ContinuousClock.Instant) -> Int { + let duration = self.startTime.duration(to: instant) + let (seconds, attoseconds) = duration.components + // Convert to microseconds + return Int(seconds * 1_000_000 + attoseconds / 1_000_000_000_000) + } + + func begin(_ label: String, _ instant: ContinuousClock.Instant) { + let entry = #"{"ph":"B","pid":1,"name":\#(JSON.serialize(label)),"ts":\#(formatTimestamp(instant: instant))}"# + if firstEntry { + firstEntry = false + output("[\n\(entry)") + } else { + output(",\n\(entry)") + } + } + + func end(_ label: String, _ instant: ContinuousClock.Instant) { + let entry = #"{"ph":"E","pid":1,"name":\#(JSON.serialize(label)),"ts":\#(formatTimestamp(instant: instant))}"# + output(",\n\(entry)") + } +} + +/// Mark a span of code with a label and measure the duration. +public func withSpan(_ label: String, body: @escaping () throws -> T) rethrows -> T { + guard let profiling = Profiling.current else { + return try body() + } + profiling.begin(label, profiling.clock.now) + defer { + profiling.end(label, profiling.clock.now) + } + return try body() +} + +/// Foundation-less JSON serialization +private enum JSON { + static func serialize(_ value: String) -> String { + // https://www.ietf.org/rfc/rfc4627.txt + var output = "\"" + for scalar in value.unicodeScalars { + switch scalar { + case "\"": + output += "\\\"" + case "\\": + output += "\\\\" + case "\u{08}": + output += "\\b" + case "\u{0C}": + output += "\\f" + case "\n": + output += "\\n" + case "\r": + output += "\\r" + case "\t": + output += "\\t" + case "\u{20}"..."\u{21}", "\u{23}"..."\u{5B}", "\u{5D}"..."\u{10FFFF}": + output.unicodeScalars.append(scalar) + default: + var hex = String(scalar.value, radix: 16, uppercase: true) + hex = String(repeating: "0", count: 4 - hex.count) + hex + output += "\\u" + hex + } + } + output += "\"" + return output + } +} + // MARK: - DiagnosticError import SwiftSyntax diff --git a/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift b/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift index 92e74e621..f9fa56c42 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift @@ -50,7 +50,9 @@ import BridgeJSUtilities static func main() throws { do { - try run() + try Profiling.with { + try run() + } } catch { printStderr("error: \(error)") exit(1) @@ -121,18 +123,22 @@ import BridgeJSUtilities let bridgeJSMacrosPath = outputDirectory.appending(path: "BridgeJS.Macros.swift") let primaryDtsPath = hasDts ? bridgeJsDtsPath.path : bridgeJsGlobalDtsPath.path let globalDtsFiles = (hasDts && hasGlobalDts) ? [bridgeJsGlobalDtsPath.path] : [] - _ = try invokeTS2Swift( - dtsFile: primaryDtsPath, - globalDtsFiles: globalDtsFiles, - tsconfigPath: tsconfigPath, - nodePath: nodePath, - progress: progress, - outputPath: bridgeJSMacrosPath.path - ) + try withSpan("invokeTS2Swift") { + _ = try invokeTS2Swift( + dtsFile: primaryDtsPath, + globalDtsFiles: globalDtsFiles, + tsconfigPath: tsconfigPath, + nodePath: nodePath, + progress: progress, + outputPath: bridgeJSMacrosPath.path + ) + } generatedMacrosPath = bridgeJSMacrosPath.path } - var inputFiles = inputSwiftFiles(targetDirectory: targetDirectory, positionalArguments: positionalArguments) + var inputFiles = withSpan("Collecting Swift files") { + return inputSwiftFiles(targetDirectory: targetDirectory, positionalArguments: positionalArguments) + } // BridgeJS.Macros.swift contains imported declarations (@JSFunction, @JSClass, etc.) that need // to be processed by SwiftToSkeleton to populate the imported skeleton. The command plugin // filters out Generated/ files, so we explicitly add it here after generation. @@ -148,22 +154,28 @@ import BridgeJSUtilities exposeToGlobal: config.exposeToGlobal ) for inputFile in inputFiles.sorted() { - let inputURL = URL(fileURLWithPath: inputFile) - // Skip directories (e.g. .docc catalogs included in target.sourceFiles) - var isDirectory: ObjCBool = false - if FileManager.default.fileExists(atPath: inputFile, isDirectory: &isDirectory), isDirectory.boolValue { - continue + try withSpan("Parsing \(inputFile)") { + let inputURL = URL(fileURLWithPath: inputFile) + // Skip directories (e.g. .docc catalogs included in target.sourceFiles) + var isDirectory: ObjCBool = false + if FileManager.default.fileExists(atPath: inputFile, isDirectory: &isDirectory), + isDirectory.boolValue + { + return + } + let content = try String(contentsOf: inputURL, encoding: .utf8) + if hasBridgeJSSkipComment(content) { + return + } + + let sourceFile = Parser.parse(source: content) + swiftToSkeleton.addSourceFile(sourceFile, inputFilePath: inputFile) } - let content = try String(contentsOf: inputURL, encoding: .utf8) - if hasBridgeJSSkipComment(content) { - continue - } - - let sourceFile = Parser.parse(source: content) - swiftToSkeleton.addSourceFile(sourceFile, inputFilePath: inputFile) } - let skeleton = try swiftToSkeleton.finalize() + let skeleton = try withSpan("SwiftToSkeleton.finalize") { + return try swiftToSkeleton.finalize() + } var exporter: ExportSwift? if let skeleton = skeleton.exported { @@ -183,10 +195,16 @@ import BridgeJSUtilities } // Generate unified closure support for both import/export to avoid duplicate symbols when concatenating. - let closureSupport = try ClosureCodegen().renderSupport(for: skeleton) + let closureSupport = try withSpan("ClosureCodegen.renderSupport") { + return try ClosureCodegen().renderSupport(for: skeleton) + } - let importResult = try importer?.finalize() - let exportResult = try exporter?.finalize() + let importResult = try withSpan("ImportTS.finalize") { + return try importer?.finalize() + } + let exportResult = try withSpan("ExportSwift.finalize") { + return try exporter?.finalize() + } // Combine and write unified Swift output let outputSwiftURL = outputDirectory.appending(path: "BridgeJS.swift") @@ -194,26 +212,30 @@ import BridgeJSUtilities let outputSwift = combineGeneratedSwift(combinedSwift) let shouldWrite = doubleDashOptions["always-write"] == "true" || !outputSwift.isEmpty if shouldWrite { + try withSpan("Writing output Swift") { + try FileManager.default.createDirectory( + at: outputSwiftURL.deletingLastPathComponent(), + withIntermediateDirectories: true, + attributes: nil + ) + try outputSwift.write(to: outputSwiftURL, atomically: true, encoding: .utf8) + } + } + + // Write unified skeleton + let outputSkeletonURL = outputDirectory.appending(path: "JavaScript/BridgeJS.json") + try withSpan("Writing output skeleton") { try FileManager.default.createDirectory( - at: outputSwiftURL.deletingLastPathComponent(), + at: outputSkeletonURL.deletingLastPathComponent(), withIntermediateDirectories: true, attributes: nil ) - try outputSwift.write(to: outputSwiftURL, atomically: true, encoding: .utf8) + let encoder = JSONEncoder() + encoder.outputFormatting = [.prettyPrinted, .sortedKeys] + let skeletonData = try encoder.encode(skeleton) + try skeletonData.write(to: outputSkeletonURL) } - // Write unified skeleton - let outputSkeletonURL = outputDirectory.appending(path: "JavaScript/BridgeJS.json") - try FileManager.default.createDirectory( - at: outputSkeletonURL.deletingLastPathComponent(), - withIntermediateDirectories: true, - attributes: nil - ) - let encoder = JSONEncoder() - encoder.outputFormatting = [.prettyPrinted, .sortedKeys] - let skeletonData = try encoder.encode(skeleton) - try skeletonData.write(to: outputSkeletonURL) - if skeleton.exported != nil || skeleton.imported != nil { progress.print("Generated BridgeJS code") } From 788ad44af6b3e327122f379a445fda7c4d10cc16 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 9 Feb 2026 11:00:49 +0900 Subject: [PATCH 06/40] [NFC] BridgeJS: Make JSGlueGen and IntrinsicJSFragment methods throwable Instead of crashing on errors in JS code generation for BridgeJSLink, we should prefer propagating errors. --- .../Sources/BridgeJSLink/BridgeJSLink.swift | 77 +++--- .../BridgeJSLink/CodeFragmentPrinter.swift | 4 +- .../Sources/BridgeJSLink/JSGlueGen.swift | 257 +++++++++--------- 3 files changed, 173 insertions(+), 165 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index 13ea4e910..d1f8363d2 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -261,11 +261,11 @@ public struct BridgeJSLink { ] } - private func generateAddImports(needsImportsObject: Bool) -> CodeFragmentPrinter { + private func generateAddImports(needsImportsObject: Bool) throws -> CodeFragmentPrinter { let printer = CodeFragmentPrinter() let allStructs = skeletons.compactMap { $0.exported?.structs }.flatMap { $0 } printer.write("return {") - printer.indent { + try printer.indent { printer.write(lines: [ "/**", " * @param {WebAssembly.Imports} importObject", @@ -273,7 +273,7 @@ public struct BridgeJSLink { "addImports: (importObject, importsContext) => {", ]) - printer.indent { + try printer.indent { printer.write(lines: [ "bjs = {};", "importObject[\"bjs\"] = bjs;", @@ -687,20 +687,21 @@ public struct BridgeJSLink { for signature in closureSignatures.sorted(by: { $0.mangleName < $1.mangleName }) { let invokeFuncName = "invoke_js_callback_\(moduleName)_\(signature.mangleName)" - printer.write( - lines: generateInvokeFunction( - signature: signature, - functionName: invokeFuncName - ) + let invokeLines = try generateInvokeFunction( + signature: signature, + functionName: invokeFuncName ) + printer.write(lines: invokeLines) let lowerFuncName = "lower_closure_\(moduleName)_\(signature.mangleName)" let makeFuncName = "make_swift_closure_\(moduleName)_\(signature.mangleName)" printer.write("bjs[\"\(makeFuncName)\"] = function(boxPtr, file, line) {") - printer.indent { - printer.write( - lines: generateLowerClosureFunction(signature: signature, functionName: lowerFuncName) + try printer.indent { + let lowerLines = try generateLowerClosureFunction( + signature: signature, + functionName: lowerFuncName ) + printer.write(lines: lowerLines) printer.write( "return \(JSGlueVariableScope.reservedMakeSwiftClosure)(boxPtr, file, line, \(lowerFuncName));" ) @@ -788,7 +789,7 @@ public struct BridgeJSLink { private func generateInvokeFunction( signature: ClosureSignature, functionName: String - ) -> [String] { + ) throws -> [String] { let printer = CodeFragmentPrinter() let scope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) let cleanupCode = CodeFragmentPrinter() @@ -806,20 +807,20 @@ public struct BridgeJSLink { printer.nextLine() printer.write("bjs[\"\(functionName)\"] = function(\(invokeParams.joined(separator: ", "))) {") - printer.indent { + try printer.indent { printer.write("try {") - printer.indent { + try printer.indent { printer.write("const callback = \(JSGlueVariableScope.reservedSwift).memory.getObject(callbackId);") for (index, paramType) in signature.parameters.enumerated() { - let fragment = try! IntrinsicJSFragment.closureLiftParameter(type: paramType) + let fragment = try IntrinsicJSFragment.closureLiftParameter(type: paramType) let args: [String] if case .nullable = paramType { args = ["param\(index)IsSome", "param\(index)Value", "param\(index)"] } else { args = ["param\(index)Id", "param\(index)"] } - _ = fragment.printCode(args, scope, printer, cleanupCode) + _ = try fragment.printCode(args, scope, printer, cleanupCode) } let callbackParams = signature.parameters.indices.map { "param\($0)" }.joined(separator: ", ") @@ -837,14 +838,14 @@ public struct BridgeJSLink { break } - let returnFragment = try! IntrinsicJSFragment.closureLowerReturn(type: signature.returnType) - _ = returnFragment.printCode(["result"], scope, printer, cleanupCode) + let returnFragment = try IntrinsicJSFragment.closureLowerReturn(type: signature.returnType) + _ = try returnFragment.printCode(["result"], scope, printer, cleanupCode) } printer.write("} catch (error) {") - printer.indent { + try printer.indent { printer.write("\(JSGlueVariableScope.reservedSetException)?.(error);") let errorFragment = IntrinsicJSFragment.closureErrorReturn(type: signature.returnType) - _ = errorFragment.printCode([], scope, printer, cleanupCode) + _ = try errorFragment.printCode([], scope, printer, cleanupCode) } printer.write("}") } @@ -857,7 +858,7 @@ public struct BridgeJSLink { private func generateLowerClosureFunction( signature: ClosureSignature, functionName: String - ) -> [String] { + ) throws -> [String] { let printer = CodeFragmentPrinter() let scope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) let cleanupCode = CodeFragmentPrinter() @@ -865,13 +866,13 @@ public struct BridgeJSLink { printer.write( "const \(functionName) = function(\(signature.parameters.indices.map { "param\($0)" }.joined(separator: ", "))) {" ) - printer.indent { + try printer.indent { var invokeArgs: [String] = ["boxPtr"] for (index, paramType) in signature.parameters.enumerated() { let paramName = "param\(index)" - let fragment = try! IntrinsicJSFragment.lowerParameter(type: paramType) - let lowered = fragment.printCode([paramName], scope, printer, cleanupCode) + let fragment = try IntrinsicJSFragment.lowerParameter(type: paramType) + let lowered = try fragment.printCode([paramName], scope, printer, cleanupCode) invokeArgs.append(contentsOf: lowered) } @@ -894,8 +895,8 @@ public struct BridgeJSLink { } printer.write("}") - let returnFragment = try! IntrinsicJSFragment.closureLiftReturn(type: signature.returnType) - _ = returnFragment.printCode([invokeResultName], scope, printer, cleanupCode) + let returnFragment = try IntrinsicJSFragment.closureLiftReturn(type: signature.returnType) + _ = try returnFragment.printCode([invokeResultName], scope, printer, cleanupCode) } printer.write("};") @@ -1073,7 +1074,7 @@ public struct BridgeJSLink { // Main function declaration printer.write("export async function createInstantiator(options, \(JSGlueVariableScope.reservedSwift)) {") - printer.indent { + try printer.indent { printer.write(lines: generateVariableDeclarations()) let bodyPrinter = CodeFragmentPrinter() @@ -1083,7 +1084,7 @@ public struct BridgeJSLink { let structScope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) let structCleanup = CodeFragmentPrinter() let fragment = IntrinsicJSFragment.structHelper(structDefinition: structDef, allStructs: allStructs) - _ = fragment.printCode([structDef.name], structScope, structPrinter, structCleanup) + _ = try fragment.printCode([structDef.name], structScope, structPrinter, structCleanup) bodyPrinter.write(lines: structPrinter.lines) } @@ -1095,11 +1096,11 @@ public struct BridgeJSLink { let enumScope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) let enumCleanup = CodeFragmentPrinter() let fragment = IntrinsicJSFragment.associatedValueEnumHelperFactory(enumDefinition: enumDef) - _ = fragment.printCode([enumDef.valuesName], enumScope, enumPrinter, enumCleanup) + _ = try fragment.printCode([enumDef.valuesName], enumScope, enumPrinter, enumCleanup) bodyPrinter.write(lines: enumPrinter.lines) } bodyPrinter.nextLine() - bodyPrinter.write(contentsOf: generateAddImports(needsImportsObject: data.needsImportsObject)) + bodyPrinter.write(contentsOf: try generateAddImports(needsImportsObject: data.needsImportsObject)) if !intrinsicRegistry.isEmpty { printer.write(lines: intrinsicRegistry.emitLines()) @@ -1356,7 +1357,7 @@ public struct BridgeJSLink { loweringFragment.parameters.count == 1, "Lowering fragment should have exactly one parameter to lower" ) - let loweredValues = loweringFragment.printCode([param.name], scope, body, cleanupCode) + let loweredValues = try loweringFragment.printCode([param.name], scope, body, cleanupCode) parameterForwardings.append(contentsOf: loweredValues) } @@ -1388,7 +1389,7 @@ public struct BridgeJSLink { body.write("const \(returnVariable) = \(call);") fragmentArguments = [returnVariable] } - let liftedValues = liftingFragment.printCode(fragmentArguments, scope, body, cleanupCode) + let liftedValues = try liftingFragment.printCode(fragmentArguments, scope, body, cleanupCode) assert(liftedValues.count <= 1, "Lifting fragment should produce at most one value") return liftedValues.first } @@ -1646,7 +1647,7 @@ public struct BridgeJSLink { switch enumDefinition.enumType { case .simple: let fragment = IntrinsicJSFragment.simpleEnumHelper(enumDefinition: enumDefinition) - _ = fragment.printCode([enumValuesName], scope, printer, cleanup) + _ = try fragment.printCode([enumValuesName], scope, printer, cleanup) jsTopLevelLines.append(contentsOf: printer.lines) case .rawValue: guard enumDefinition.rawType != nil else { @@ -1654,11 +1655,11 @@ public struct BridgeJSLink { } let fragment = IntrinsicJSFragment.rawValueEnumHelper(enumDefinition: enumDefinition) - _ = fragment.printCode([enumValuesName], scope, printer, cleanup) + _ = try fragment.printCode([enumValuesName], scope, printer, cleanup) jsTopLevelLines.append(contentsOf: printer.lines) case .associatedValue: let fragment = IntrinsicJSFragment.associatedValueEnumValues(enumDefinition: enumDefinition) - _ = fragment.printCode([enumValuesName], scope, printer, cleanup) + _ = try fragment.printCode([enumValuesName], scope, printer, cleanup) jsTopLevelLines.append(contentsOf: printer.lines) case .namespace: break @@ -2252,7 +2253,7 @@ extension BridgeJSLink { valuesToLift = liftingFragment.parameters.map { scope.variable(param.name + $0.capitalizedFirstLetter) } parameterNames.append(contentsOf: valuesToLift) } - let liftedValues = liftingFragment.printCode(valuesToLift, scope, body, cleanupCode) + let liftedValues = try liftingFragment.printCode(valuesToLift, scope, body, cleanupCode) assert(liftedValues.count == 1, "Lifting fragment should produce exactly one value") parameterForwardings.append(contentsOf: liftedValues) } @@ -2362,7 +2363,7 @@ extension BridgeJSLink { ) let fragment = try IntrinsicJSFragment.protocolPropertyOptionalToSideChannel(wrappedType: wrappedType) - _ = fragment.printCode([resultVar], scope, body, cleanupCode) + _ = try fragment.printCode([resultVar], scope, body, cleanupCode) return nil // Side-channel types return nil (no direct return value) } @@ -2415,7 +2416,7 @@ extension BridgeJSLink { 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) + let loweredValues = try loweringFragment.printCode(returnExpr.map { [$0] } ?? [], scope, body, cleanupCode) assert(loweredValues.count <= 1, "Lowering fragment should produce at most one value") return loweredValues.first } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/CodeFragmentPrinter.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/CodeFragmentPrinter.swift index 8c5a47b23..4bad3dd34 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/CodeFragmentPrinter.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/CodeFragmentPrinter.swift @@ -6,10 +6,10 @@ final class JSIntrinsicRegistry { entries.isEmpty } - func register(name: String, build: (CodeFragmentPrinter) -> Void) { + func register(name: String, build: (CodeFragmentPrinter) throws -> Void) rethrows { guard entries[name] == nil else { return } let printer = CodeFragmentPrinter() - build(printer) + try build(printer) entries[name] = printer.lines } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 68230e8d1..9402cdd9d 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -83,8 +83,8 @@ final class JSGlueVariableScope { return suffixedName } - func registerIntrinsic(_ name: String, build: (CodeFragmentPrinter) -> Void) { - intrinsicRegistry.register(name: name, build: build) + func registerIntrinsic(_ name: String, build: (CodeFragmentPrinter) throws -> Void) rethrows { + try intrinsicRegistry.register(name: name, build: build) } func makeChildScope() -> JSGlueVariableScope { @@ -162,7 +162,7 @@ struct IntrinsicJSFragment: Sendable { _ scope: JSGlueVariableScope, _ printer: CodeFragmentPrinter, _ cleanupCode: CodeFragmentPrinter - ) -> [String] + ) throws -> [String] /// A fragment that does nothing static let void = IntrinsicJSFragment( @@ -505,7 +505,7 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, scope, printer, cleanupCode in - let lowered = jsValueLower.printCode(arguments, scope, printer, cleanupCode) + let lowered = try jsValueLower.printCode(arguments, scope, printer, cleanupCode) let kindVar = lowered[0] let payload1Var = lowered[1] let payload2Var = lowered[2] @@ -521,7 +521,7 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, scope, printer, cleanupCode in - let lowered = jsValueLower.printCode(arguments, scope, printer, cleanupCode) + let lowered = try jsValueLower.printCode(arguments, scope, printer, cleanupCode) let kindVar = lowered[0] let payload1Var = lowered[1] let payload2Var = lowered[2] @@ -627,7 +627,7 @@ struct IntrinsicJSFragment: Sendable { parameters: ["isSome", "kind", "payload1", "payload2"], printCode: { arguments, scope, printer, cleanupCode in let isSome = arguments[0] - let lifted = jsValueLiftParameter.printCode( + let lifted = try jsValueLiftParameter.printCode( [arguments[1], arguments[2], arguments[3]], scope, printer, @@ -723,9 +723,9 @@ struct IntrinsicJSFragment: Sendable { let arrayVar = scope.variable("arrayValue") printer.write("let \(arrayVar);") printer.write("if (\(isSome)) {") - printer.indent { - let arrayLiftFragment = try! arrayLift(elementType: elementType) - let liftResults = arrayLiftFragment.printCode([], scope, printer, cleanupCode) + try printer.indent { + let arrayLiftFragment = try arrayLift(elementType: elementType) + let liftResults = try arrayLiftFragment.printCode([], scope, printer, cleanupCode) if let liftResult = liftResults.first { printer.write("\(arrayVar) = \(liftResult);") } @@ -740,9 +740,9 @@ struct IntrinsicJSFragment: Sendable { let dictVar = scope.variable("dictValue") printer.write("let \(dictVar);") printer.write("if (\(isSome)) {") - printer.indent { - let dictLiftFragment = try! dictionaryLift(valueType: valueType) - let liftResults = dictLiftFragment.printCode([], scope, printer, cleanupCode) + try printer.indent { + let dictLiftFragment = try dictionaryLift(valueType: valueType) + let liftResults = try dictLiftFragment.printCode([], scope, printer, cleanupCode) if let liftResult = liftResults.first { printer.write("\(dictVar) = \(liftResult);") } @@ -805,7 +805,7 @@ struct IntrinsicJSFragment: Sendable { return ["+\(isSomeVar)", "\(isSomeVar) ? \(idVar) : 0", "\(isSomeVar) ? \(bytesVar).length : 0"] case .jsValue: - let lowered = jsValueLower.printCode([value], scope, printer, cleanupCode) + let lowered = try jsValueLower.printCode([value], scope, printer, cleanupCode) return ["+\(isSomeVar)"] + lowered case .associatedValueEnum(let fullName): let base = fullName.components(separatedBy: ".").last ?? fullName @@ -833,10 +833,10 @@ struct IntrinsicJSFragment: Sendable { let cleanupArrayVar = scope.variable("\(value)Cleanups") printer.write("const \(cleanupArrayVar) = [];") printer.write("if (\(isSomeVar)) {") - printer.indent { - let arrayLowerFragment = try! arrayLower(elementType: elementType) + try printer.indent { + let arrayLowerFragment = try arrayLower(elementType: elementType) let arrayCleanup = CodeFragmentPrinter() - let _ = arrayLowerFragment.printCode([value], scope, printer, arrayCleanup) + let _ = try arrayLowerFragment.printCode([value], scope, printer, arrayCleanup) if !arrayCleanup.lines.isEmpty { for line in arrayCleanup.lines { printer.write("\(cleanupArrayVar).push(() => { \(line) });") @@ -850,10 +850,10 @@ struct IntrinsicJSFragment: Sendable { let cleanupArrayVar = scope.variable("\(value)Cleanups") printer.write("const \(cleanupArrayVar) = [];") printer.write("if (\(isSomeVar)) {") - printer.indent { - let dictLowerFragment = try! dictionaryLower(valueType: valueType) + try printer.indent { + let dictLowerFragment = try dictionaryLower(valueType: valueType) let dictCleanup = CodeFragmentPrinter() - let _ = dictLowerFragment.printCode([value], scope, printer, dictCleanup) + let _ = try dictLowerFragment.printCode([value], scope, printer, dictCleanup) if !dictCleanup.lines.isEmpty { for line in dictCleanup.lines { printer.write("\(cleanupArrayVar).push(() => { \(line) });") @@ -1002,9 +1002,9 @@ struct IntrinsicJSFragment: Sendable { printer.write("const \(isSomeVar) = \(scope.popI32());") printer.write("let \(resultVar);") printer.write("if (\(isSomeVar)) {") - printer.indent { - let arrayLiftFragment = try! arrayLift(elementType: elementType) - let liftResults = arrayLiftFragment.printCode([], scope, printer, cleanupCode) + try printer.indent { + let arrayLiftFragment = try arrayLift(elementType: elementType) + let liftResults = try arrayLiftFragment.printCode([], scope, printer, cleanupCode) if let liftResult = liftResults.first { printer.write("\(resultVar) = \(liftResult);") } @@ -1019,9 +1019,9 @@ struct IntrinsicJSFragment: Sendable { printer.write("const \(isSomeVar) = \(scope.popI32());") printer.write("let \(resultVar);") printer.write("if (\(isSomeVar)) {") - printer.indent { - let dictLiftFragment = try! dictionaryLift(valueType: valueType) - let liftResults = dictLiftFragment.printCode([], scope, printer, cleanupCode) + try printer.indent { + let dictLiftFragment = try dictionaryLift(valueType: valueType) + let liftResults = try dictLiftFragment.printCode([], scope, printer, cleanupCode) if let liftResult = liftResults.first { printer.write("\(resultVar) = \(liftResult);") } @@ -1036,8 +1036,8 @@ struct IntrinsicJSFragment: Sendable { printer.write("const \(isSomeVar) = \(scope.popI32());") printer.write("let \(resultVar);") printer.write("if (\(isSomeVar)) {") - printer.indent { - let lifted = jsValueLift.printCode([], scope, printer, cleanupCode) + try printer.indent { + let lifted = try jsValueLift.printCode([], scope, printer, cleanupCode) if let liftedValue = lifted.first { printer.write("\(resultVar) = \(liftedValue);") } @@ -1111,7 +1111,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("bjs[\"swift_js_return_optional_object\"](\(isSomeVar) ? 1 : 0, \(idVar));") case .jsValue: if value != "undefined" { - let lowered = jsValueLower.printCode([value], scope, printer, cleanupCode) + let lowered = try jsValueLower.printCode([value], scope, printer, cleanupCode) let kindVar = lowered[0] let payload1Var = lowered[1] let payload2Var = lowered[2] @@ -1122,10 +1122,10 @@ struct IntrinsicJSFragment: Sendable { scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) case .array(let elementType): printer.write("if (\(isSomeVar)) {") - printer.indent { - let arrayLowerFragment = try! arrayLower(elementType: elementType) + try printer.indent { + let arrayLowerFragment = try arrayLower(elementType: elementType) let arrayCleanup = CodeFragmentPrinter() - let _ = arrayLowerFragment.printCode([value], scope, printer, arrayCleanup) + let _ = try arrayLowerFragment.printCode([value], scope, printer, arrayCleanup) if !arrayCleanup.lines.isEmpty { for line in arrayCleanup.lines { printer.write(line) @@ -1185,21 +1185,21 @@ struct IntrinsicJSFragment: Sendable { cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") case .dictionary(let valueType): printer.write("if (\(isSomeVar)) {") - printer.indent { + try printer.indent { let cleanupArrayVar = scope.variable("arrayCleanups") let entriesVar = scope.variable("entries") let entryVar = scope.variable("entry") printer.write("const \(cleanupArrayVar) = [];") printer.write("const \(entriesVar) = Object.entries(\(value));") printer.write("for (const \(entryVar) of \(entriesVar)) {") - printer.indent { + try printer.indent { let keyVar = scope.variable("key") let valueVar = scope.variable("value") printer.write("const [\(keyVar), \(valueVar)] = \(entryVar);") - let keyFragment = try! stackLowerFragment(elementType: .string) + let keyFragment = try stackLowerFragment(elementType: .string) let keyCleanup = CodeFragmentPrinter() - let _ = keyFragment.printCode([keyVar], scope, printer, keyCleanup) + let _ = try keyFragment.printCode([keyVar], scope, printer, keyCleanup) if !keyCleanup.lines.isEmpty { printer.write("\(cleanupArrayVar).push(() => {") printer.indent { @@ -1210,9 +1210,9 @@ struct IntrinsicJSFragment: Sendable { printer.write("});") } - let valueFragment = try! stackLowerFragment(elementType: valueType) + let valueFragment = try stackLowerFragment(elementType: valueType) let valueCleanup = CodeFragmentPrinter() - let _ = valueFragment.printCode([valueVar], scope, printer, valueCleanup) + let _ = try valueFragment.printCode([valueVar], scope, printer, valueCleanup) if !valueCleanup.lines.isEmpty { printer.write("\(cleanupArrayVar).push(() => {") printer.indent { @@ -1302,7 +1302,7 @@ struct IntrinsicJSFragment: Sendable { parameters: ["value", "targetVar"], printCode: { arguments, scope, printer, cleanupCode in let baseFragment = boolLiftParameter - let lifted = baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lifted = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) printer.write("let \(arguments[1]) = \(lifted[0]);") return [] } @@ -1312,7 +1312,7 @@ struct IntrinsicJSFragment: Sendable { parameters: ["objectId", "targetVar"], printCode: { arguments, scope, printer, cleanupCode in let baseFragment = stringLiftParameter - let lifted = baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lifted = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) printer.write("let \(arguments[1]) = String(\(lifted[0]));") return [] } @@ -1324,7 +1324,7 @@ struct IntrinsicJSFragment: Sendable { parameters: ["objectId", "targetVar"], printCode: { arguments, scope, printer, cleanupCode in let baseFragment = stringLiftParameter - let lifted = baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lifted = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) printer.write("let \(arguments[1]) = String(\(lifted[0]));") return [] } @@ -1334,7 +1334,7 @@ struct IntrinsicJSFragment: Sendable { parameters: ["value", "targetVar"], printCode: { arguments, scope, printer, cleanupCode in let baseFragment = boolLiftParameter - let lifted = baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lifted = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) printer.write("let \(arguments[1]) = \(lifted[0]);") return [] } @@ -1494,7 +1494,7 @@ struct IntrinsicJSFragment: Sendable { parameters: ["result"], printCode: { arguments, scope, printer, cleanupCode in let baseFragment = boolLowerReturn - let lowered = baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lowered = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) printer.write("return \(lowered[0]);") return [] } @@ -1520,7 +1520,7 @@ struct IntrinsicJSFragment: Sendable { parameters: ["result"], printCode: { arguments, scope, printer, cleanupCode in let baseFragment = stringLowerReturn - let lowered = baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lowered = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) printer.write("return \(lowered[0]);") return [] } @@ -1530,7 +1530,7 @@ struct IntrinsicJSFragment: Sendable { parameters: ["result"], printCode: { arguments, scope, printer, cleanupCode in let baseFragment = jsObjectLowerReturn - let lowered = baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lowered = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) printer.write("return \(lowered[0]);") return [] } @@ -1540,7 +1540,7 @@ struct IntrinsicJSFragment: Sendable { parameters: ["result"], printCode: { arguments, scope, printer, cleanupCode in let baseFragment = swiftHeapObjectLowerReturn - let lowered = baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lowered = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) printer.write("return \(lowered[0]);") return [] } @@ -1552,7 +1552,7 @@ struct IntrinsicJSFragment: Sendable { parameters: ["result"], printCode: { arguments, scope, printer, cleanupCode in let baseFragment = stringLowerReturn - let lowered = baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lowered = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) printer.write("return \(lowered[0]);") return [] } @@ -1562,7 +1562,7 @@ struct IntrinsicJSFragment: Sendable { parameters: ["result"], printCode: { arguments, scope, printer, cleanupCode in let baseFragment = boolLowerReturn - let lowered = baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lowered = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) printer.write("return \(lowered[0]);") return [] } @@ -1697,7 +1697,7 @@ struct IntrinsicJSFragment: Sendable { parameters: ["invokeCall"], printCode: { arguments, scope, printer, cleanupCode in let baseFragment = boolLiftReturn - let lifted = baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lifted = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) printer.write("return \(lifted[0]);") return [] } @@ -1716,7 +1716,7 @@ struct IntrinsicJSFragment: Sendable { printCode: { arguments, scope, printer, cleanupCode in printer.write("const resultLen = \(arguments[0]);") let baseFragment = stringLiftReturn - let lifted = baseFragment.printCode([], scope, printer, cleanupCode) + let lifted = try baseFragment.printCode([], scope, printer, cleanupCode) printer.write("return \(lifted[0]);") return [] } @@ -1727,7 +1727,7 @@ struct IntrinsicJSFragment: Sendable { printCode: { arguments, scope, printer, cleanupCode in printer.write("const resultId = \(arguments[0]);") let baseFragment = jsObjectLiftReturn - let lifted = baseFragment.printCode(["resultId"], scope, printer, cleanupCode) + let lifted = try baseFragment.printCode(["resultId"], scope, printer, cleanupCode) printer.write("return \(lifted[0]);") return [] } @@ -1763,7 +1763,7 @@ struct IntrinsicJSFragment: Sendable { printCode: { arguments, scope, printer, cleanupCode in printer.write("const resultLen = \(arguments[0]);") let baseFragment = stringLiftReturn - let lifted = baseFragment.printCode([], scope, printer, cleanupCode) + let lifted = try baseFragment.printCode([], scope, printer, cleanupCode) printer.write("return \(lifted[0]);") return [] } @@ -1773,7 +1773,7 @@ struct IntrinsicJSFragment: Sendable { parameters: ["invokeCall"], printCode: { arguments, scope, printer, cleanupCode in let baseFragment = boolLiftReturn - let lifted = baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lifted = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) printer.write("return \(lifted[0]);") return [] } @@ -1823,7 +1823,7 @@ struct IntrinsicJSFragment: Sendable { context: .importTS, kind: kind ) - let lifted = baseFragment.printCode([], scope, printer, cleanupCode) + let lifted = try baseFragment.printCode([], scope, printer, cleanupCode) if !lifted.isEmpty { printer.write("return \(lifted[0]);") } @@ -2186,10 +2186,10 @@ struct IntrinsicJSFragment: Sendable { // Generate lower function printer.write("lower: (value) => {") - printer.indent { + try printer.indent { printer.write("const enumTag = value.tag;") printer.write("switch (enumTag) {") - printer.indent { + try printer.indent { let lowerPrinter = CodeFragmentPrinter() for enumCase in enumDefinition.cases { let caseName = enumCase.name.capitalizedFirstLetter @@ -2197,7 +2197,12 @@ struct IntrinsicJSFragment: Sendable { let caseCleanup = CodeFragmentPrinter() caseCleanup.indent() let fragment = IntrinsicJSFragment.associatedValuePushPayload(enumCase: enumCase) - _ = fragment.printCode(["value", enumName, caseName], caseScope, lowerPrinter, caseCleanup) + _ = try fragment.printCode( + ["value", enumName, caseName], + caseScope, + lowerPrinter, + caseCleanup + ) } for line in lowerPrinter.lines { @@ -2214,10 +2219,10 @@ struct IntrinsicJSFragment: Sendable { printer.write( "lift: (tag) => {" ) - printer.indent { + try printer.indent { printer.write("tag = tag | 0;") printer.write("switch (tag) {") - printer.indent { + try printer.indent { let liftPrinter = CodeFragmentPrinter() for enumCase in enumDefinition.cases { let caseName = enumCase.name.capitalizedFirstLetter @@ -2225,7 +2230,7 @@ struct IntrinsicJSFragment: Sendable { let caseCleanup = CodeFragmentPrinter() let fragment = IntrinsicJSFragment.associatedValuePopPayload(enumCase: enumCase) - _ = fragment.printCode([enumName, caseName], caseScope, liftPrinter, caseCleanup) + _ = try fragment.printCode([enumName, caseName], caseScope, liftPrinter, caseCleanup) } for line in liftPrinter.lines { @@ -2306,7 +2311,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("case \(enumName).Tag.\(caseName): {") - printer.indent { + try printer.indent { if enumCase.associatedValues.isEmpty { printer.write("const cleanup = undefined;") printer.write("return { caseId: \(enumName).Tag.\(caseName), cleanup };") @@ -2316,9 +2321,11 @@ struct IntrinsicJSFragment: Sendable { for (associatedValueIndex, associatedValue) in reversedValues { let prop = associatedValue.label ?? "param\(associatedValueIndex)" - let fragment = IntrinsicJSFragment.associatedValuePushPayload(type: associatedValue.type) + let fragment = try IntrinsicJSFragment.associatedValuePushPayload( + type: associatedValue.type + ) - _ = fragment.printCode(["value.\(prop)"], scope, printer, cleanup) + _ = try fragment.printCode(["value.\(prop)"], scope, printer, cleanup) } if cleanup.lines.isEmpty { @@ -2355,9 +2362,9 @@ struct IntrinsicJSFragment: Sendable { // Process associated values in reverse order (to match the order they'll be popped) for (associatedValueIndex, associatedValue) in enumCase.associatedValues.enumerated().reversed() { let prop = associatedValue.label ?? "param\(associatedValueIndex)" - let fragment = IntrinsicJSFragment.associatedValuePopPayload(type: associatedValue.type) + let fragment = try IntrinsicJSFragment.associatedValuePopPayload(type: associatedValue.type) - let result = fragment.printCode([], scope, casePrinter, cleanup) + let result = try fragment.printCode([], scope, casePrinter, cleanup) let varName = result.first ?? "value_\(associatedValueIndex)" fieldPairs.append("\(prop): \(varName)") @@ -2380,12 +2387,12 @@ struct IntrinsicJSFragment: Sendable { ) } - private static func associatedValuePushPayload(type: BridgeType) -> IntrinsicJSFragment { + private static func associatedValuePushPayload(type: BridgeType) throws -> IntrinsicJSFragment { switch type { case .nullable(let wrappedType, let kind): return associatedValueOptionalPushPayload(wrappedType: wrappedType, kind: kind) default: - return try! stackLowerFragment(elementType: type) + return try stackLowerFragment(elementType: type) } } @@ -2551,10 +2558,10 @@ struct IntrinsicJSFragment: Sendable { let arrCleanupVar = scope.variable("arrCleanup") printer.write("let \(arrCleanupVar);") printer.write("if (\(isSomeVar)) {") - printer.indent { + try printer.indent { let localCleanup = CodeFragmentPrinter() - let arrFragment = try! arrayLower(elementType: elementType) - _ = arrFragment.printCode([value], scope, printer, localCleanup) + let arrFragment = try arrayLower(elementType: elementType) + _ = try arrFragment.printCode([value], scope, printer, localCleanup) let cleanupLines = localCleanup.lines.filter { !$0.trimmingCharacters(in: .whitespaces).isEmpty } @@ -2580,12 +2587,12 @@ struct IntrinsicJSFragment: Sendable { ) } - private static func associatedValuePopPayload(type: BridgeType) -> IntrinsicJSFragment { + private static func associatedValuePopPayload(type: BridgeType) throws -> IntrinsicJSFragment { switch type { case .nullable(let wrappedType, let kind): return associatedValueOptionalPopPayload(wrappedType: wrappedType, kind: kind) default: - return try! stackLiftFragment(elementType: type) + return try stackLiftFragment(elementType: type) } } @@ -2602,7 +2609,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("const \(isSomeVar) = \(scope.popI32());") printer.write("let \(optVar);") printer.write("if (\(isSomeVar)) {") - printer.indent { + try printer.indent { // For optional associated value enums, Swift uses bridgeJSLowerParameter() // which pushes caseId to i32Stack (not tagStack like bridgeJSLowerReturn()). if case .associatedValueEnum(let fullName) = wrappedType { @@ -2613,8 +2620,8 @@ struct IntrinsicJSFragment: Sendable { "\(optVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(caseIdVar));" ) } else { - let wrappedFragment = associatedValuePopPayload(type: wrappedType) - let wrappedResults = wrappedFragment.printCode([], scope, printer, cleanup) + let wrappedFragment = try associatedValuePopPayload(type: wrappedType) + let wrappedResults = try wrappedFragment.printCode([], scope, printer, cleanup) if let wrappedResult = wrappedResults.first { printer.write("\(optVar) = \(wrappedResult);") } else { @@ -2690,10 +2697,10 @@ struct IntrinsicJSFragment: Sendable { printer.write("const \(cleanupArrayVar) = [];") let elemVar = scope.variable("elem") printer.write("for (const \(elemVar) of \(arr)) {") - printer.indent { - let elementFragment = try! stackLowerFragment(elementType: elementType) + try printer.indent { + let elementFragment = try stackLowerFragment(elementType: elementType) let elementCleanup = CodeFragmentPrinter() - let _ = elementFragment.printCode([elemVar], scope, printer, elementCleanup) + let _ = try elementFragment.printCode([elemVar], scope, printer, elementCleanup) if !elementCleanup.lines.isEmpty { printer.write("\(cleanupArrayVar).push(() => {") printer.indent { @@ -2725,14 +2732,14 @@ struct IntrinsicJSFragment: Sendable { let entryVar = scope.variable("entry") printer.write("const \(entriesVar) = Object.entries(\(dict));") printer.write("for (const \(entryVar) of \(entriesVar)) {") - printer.indent { + try printer.indent { let keyVar = scope.variable("key") let valueVar = scope.variable("value") printer.write("const [\(keyVar), \(valueVar)] = \(entryVar);") - let keyFragment = try! stackLowerFragment(elementType: .string) + let keyFragment = try stackLowerFragment(elementType: .string) let keyCleanup = CodeFragmentPrinter() - let _ = keyFragment.printCode([keyVar], scope, printer, keyCleanup) + let _ = try keyFragment.printCode([keyVar], scope, printer, keyCleanup) if !keyCleanup.lines.isEmpty { printer.write("\(cleanupArrayVar).push(() => {") printer.indent { @@ -2743,9 +2750,9 @@ struct IntrinsicJSFragment: Sendable { printer.write("});") } - let valueFragment = try! stackLowerFragment(elementType: valueType) + let valueFragment = try stackLowerFragment(elementType: valueType) let valueCleanup = CodeFragmentPrinter() - let _ = valueFragment.printCode([valueVar], scope, printer, valueCleanup) + let _ = try valueFragment.printCode([valueVar], scope, printer, valueCleanup) if !valueCleanup.lines.isEmpty { printer.write("\(cleanupArrayVar).push(() => {") printer.indent { @@ -2776,9 +2783,9 @@ struct IntrinsicJSFragment: Sendable { printer.write("const \(lenVar) = \(scope.popI32());") printer.write("const \(resultVar) = [];") printer.write("for (let \(iVar) = 0; \(iVar) < \(lenVar); \(iVar)++) {") - printer.indent { - let elementFragment = try! stackLiftFragment(elementType: elementType) - let elementResults = elementFragment.printCode([], scope, printer, cleanupCode) + try printer.indent { + let elementFragment = try stackLiftFragment(elementType: elementType) + let elementResults = try elementFragment.printCode([], scope, printer, cleanupCode) if let elementExpr = elementResults.first { printer.write("\(resultVar).push(\(elementExpr));") } @@ -2802,11 +2809,11 @@ struct IntrinsicJSFragment: Sendable { printer.write("const \(lenVar) = \(scope.popI32());") printer.write("const \(resultVar) = {};") printer.write("for (let \(iVar) = 0; \(iVar) < \(lenVar); \(iVar)++) {") - printer.indent { - let valueFragment = try! stackLiftFragment(elementType: valueType) - let valueResults = valueFragment.printCode([], scope, printer, cleanupCode) - let keyFragment = try! stackLiftFragment(elementType: .string) - let keyResults = keyFragment.printCode([], scope, printer, cleanupCode) + try printer.indent { + let valueFragment = try stackLiftFragment(elementType: valueType) + let valueResults = try valueFragment.printCode([], scope, printer, cleanupCode) + let keyFragment = try stackLiftFragment(elementType: .string) + let keyResults = try keyFragment.printCode([], scope, printer, cleanupCode) if let keyExpr = keyResults.first, let valueExpr = valueResults.first { printer.write("\(resultVar)[\(keyExpr)] = \(valueExpr);") } @@ -2978,9 +2985,9 @@ struct IntrinsicJSFragment: Sendable { } ) case .array(let innerElementType): - return try! arrayLift(elementType: innerElementType) + return try arrayLift(elementType: innerElementType) case .dictionary(let valueType): - return try! dictionaryLift(valueType: valueType) + return try dictionaryLift(valueType: valueType) case .nullable(let wrappedType, let kind): return try optionalElementRaiseFragment(wrappedType: wrappedType, kind: kind) case .unsafePointer: @@ -3004,7 +3011,7 @@ struct IntrinsicJSFragment: Sendable { parameters: ["value"], printCode: { arguments, scope, printer, cleanup in registerJSValueHelpers(scope: scope) - let lowered = jsValueLower.printCode([arguments[0]], scope, printer, cleanup) + let lowered = try jsValueLower.printCode([arguments[0]], scope, printer, cleanup) let kindVar = lowered[0] let payload1Var = lowered[1] let payload2Var = lowered[2] @@ -3165,9 +3172,9 @@ struct IntrinsicJSFragment: Sendable { } ) case .array(let innerElementType): - return try! arrayLower(elementType: innerElementType) + return try arrayLower(elementType: innerElementType) case .dictionary(let valueType): - return try! dictionaryLower(valueType: valueType) + return try dictionaryLower(valueType: valueType) case .nullable(let wrappedType, let kind): return try optionalElementLowerFragment( wrappedType: wrappedType, @@ -3216,9 +3223,9 @@ struct IntrinsicJSFragment: Sendable { printer.write("\(resultVar) = \(absenceLiteral);") } printer.write("} else {") - printer.indent { - let innerFragment = try! stackLiftFragment(elementType: wrappedType) - let innerResults = innerFragment.printCode([], scope, printer, cleanup) + try printer.indent { + let innerFragment = try stackLiftFragment(elementType: wrappedType) + let innerResults = try innerFragment.printCode([], scope, printer, cleanup) if let innerResult = innerResults.first { printer.write("\(resultVar) = \(innerResult);") } else { @@ -3247,9 +3254,9 @@ struct IntrinsicJSFragment: Sendable { // Cleanup is written inside the if block so retained id is in scope let localCleanupWriter = CodeFragmentPrinter() printer.write("if (\(isSomeVar)) {") - printer.indent { - let innerFragment = try! stackLowerFragment(elementType: wrappedType) - let _ = innerFragment.printCode([value], scope, printer, localCleanupWriter) + try printer.indent { + let innerFragment = try stackLowerFragment(elementType: wrappedType) + let _ = try innerFragment.printCode([value], scope, printer, localCleanupWriter) let localCleanupLines = localCleanupWriter.lines.filter { !$0.trimmingCharacters(in: .whitespaces).isEmpty } @@ -3302,8 +3309,8 @@ struct IntrinsicJSFragment: Sendable { printer.indent() printer.write("lower: (value) => {") - printer.indent { - generateStructLowerCode( + try printer.indent { + try generateStructLowerCode( structDef: capturedStructDef, allStructs: capturedAllStructs, scope: scope, @@ -3315,8 +3322,8 @@ struct IntrinsicJSFragment: Sendable { printer.write( "lift: () => {" ) - printer.indent { - generateStructLiftCode( + try printer.indent { + try generateStructLiftCode( structDef: capturedStructDef, allStructs: capturedAllStructs, scope: scope, @@ -3344,7 +3351,7 @@ struct IntrinsicJSFragment: Sendable { allStructs: [ExportedStruct], scope: JSGlueVariableScope, printer: CodeFragmentPrinter - ) { + ) throws { let lowerPrinter = CodeFragmentPrinter() let lowerScope = scope.makeChildScope() let lowerCleanup = CodeFragmentPrinter() @@ -3352,9 +3359,9 @@ struct IntrinsicJSFragment: Sendable { let instanceProps = structDef.properties.filter { !$0.isStatic } for property in instanceProps { - let fragment = structFieldLowerFragment(field: property, allStructs: allStructs) + let fragment = try structFieldLowerFragment(field: property, allStructs: allStructs) let fieldValue = "value.\(property.name)" - _ = fragment.printCode([fieldValue], lowerScope, lowerPrinter, lowerCleanup) + _ = try fragment.printCode([fieldValue], lowerScope, lowerPrinter, lowerCleanup) } for line in lowerPrinter.lines { @@ -3377,7 +3384,7 @@ struct IntrinsicJSFragment: Sendable { scope: JSGlueVariableScope, printer: CodeFragmentPrinter, attachMethods: Bool = false - ) { + ) throws { let liftScope = scope.makeChildScope() let liftCleanup = CodeFragmentPrinter() @@ -3385,8 +3392,8 @@ struct IntrinsicJSFragment: Sendable { let instanceProps = structDef.properties.filter { !$0.isStatic } for property in instanceProps.reversed() { - let fragment = structFieldLiftFragment(field: property, allStructs: allStructs) - let results = fragment.printCode([], liftScope, printer, liftCleanup) + let fragment = try structFieldLiftFragment(field: property, allStructs: allStructs) + let results = try fragment.printCode([], liftScope, printer, liftCleanup) if let resultExpr = results.first { fieldExpressions.append((property.name, resultExpr)) @@ -3411,7 +3418,7 @@ struct IntrinsicJSFragment: Sendable { printer.write( "\(instanceVar).\(method.name) = function(\(paramList)) {" ) - printer.indent { + try printer.indent { let methodScope = scope.makeChildScope() let methodCleanup = CodeFragmentPrinter() @@ -3422,8 +3429,8 @@ struct IntrinsicJSFragment: Sendable { var paramForwardings: [String] = [] for param in method.parameters { - let fragment = try! IntrinsicJSFragment.lowerParameter(type: param.type) - let loweredValues = fragment.printCode([param.name], methodScope, printer, methodCleanup) + let fragment = try IntrinsicJSFragment.lowerParameter(type: param.type) + let loweredValues = try fragment.printCode([param.name], methodScope, printer, methodCleanup) paramForwardings.append(contentsOf: loweredValues) } @@ -3440,9 +3447,9 @@ struct IntrinsicJSFragment: Sendable { // Lift return value if needed if method.returnType != .void { - let liftFragment = try! IntrinsicJSFragment.liftReturn(type: method.returnType) + let liftFragment = try IntrinsicJSFragment.liftReturn(type: method.returnType) let liftArgs = liftFragment.parameters.isEmpty ? [] : ["ret"] - let lifted = liftFragment.printCode(liftArgs, methodScope, printer, methodCleanup) + let lifted = try liftFragment.printCode(liftArgs, methodScope, printer, methodCleanup) if let liftedValue = lifted.first { printer.write("return \(liftedValue);") } @@ -3460,7 +3467,7 @@ struct IntrinsicJSFragment: Sendable { private static func structFieldLowerFragment( field: ExportedProperty, allStructs: [ExportedStruct] - ) -> IntrinsicJSFragment { + ) throws -> IntrinsicJSFragment { switch field.type { case .jsValue: preconditionFailure("Struct field of JSValue is not supported yet") @@ -3724,7 +3731,7 @@ struct IntrinsicJSFragment: Sendable { scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) cleanup.write("if (\(enumCleanupVar)) { \(enumCleanupVar)(); }") default: - let wrappedFragment = structFieldLowerFragment( + let wrappedFragment = try structFieldLowerFragment( field: ExportedProperty( name: field.name, type: wrappedType, @@ -3735,7 +3742,7 @@ struct IntrinsicJSFragment: Sendable { ) let guardedPrinter = CodeFragmentPrinter() let guardedCleanup = CodeFragmentPrinter() - _ = wrappedFragment.printCode([value], scope, guardedPrinter, guardedCleanup) + _ = try wrappedFragment.printCode([value], scope, guardedPrinter, guardedCleanup) var loweredLines = guardedPrinter.lines var hoistedCleanupVar: String? if let first = loweredLines.first { @@ -3794,7 +3801,7 @@ struct IntrinsicJSFragment: Sendable { } ) default: - return try! stackLowerFragment(elementType: field.type) + return try stackLowerFragment(elementType: field.type) } } @@ -3846,7 +3853,7 @@ struct IntrinsicJSFragment: Sendable { private static func structFieldLiftFragment( field: ExportedProperty, allStructs: [ExportedStruct] - ) -> IntrinsicJSFragment { + ) throws -> IntrinsicJSFragment { switch field.type { case .jsValue: preconditionFailure("Struct field of JSValue is not supported yet") @@ -3859,7 +3866,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("const \(isSomeVar) = \(scope.popI32());") printer.write("let \(optVar);") printer.write("if (\(isSomeVar)) {") - printer.indent { + try printer.indent { // Special handling for associated value enum - in struct fields, case ID is pushed to i32Stack if case .associatedValueEnum(let enumName) = wrappedType { let base = enumName.components(separatedBy: ".").last ?? enumName @@ -3869,7 +3876,7 @@ struct IntrinsicJSFragment: Sendable { "\(optVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(caseIdVar), );" ) } else { - let wrappedFragment = structFieldLiftFragment( + let wrappedFragment = try structFieldLiftFragment( field: ExportedProperty( name: field.name, type: wrappedType, @@ -3878,7 +3885,7 @@ struct IntrinsicJSFragment: Sendable { ), allStructs: allStructs ) - let wrappedResults = wrappedFragment.printCode([], scope, printer, cleanup) + let wrappedResults = try wrappedFragment.printCode([], scope, printer, cleanup) if let wrappedResult = wrappedResults.first { printer.write("\(optVar) = \(wrappedResult);") } else { @@ -3938,7 +3945,7 @@ struct IntrinsicJSFragment: Sendable { } ) default: - return try! stackLiftFragment(elementType: field.type) + return try stackLiftFragment(elementType: field.type) } } } From 3d9678a2331967ebb937b66d4a8324d06af9451b Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 9 Feb 2026 11:50:40 +0900 Subject: [PATCH 07/40] BridgeJS: Build fixes for profiling API --- .../BridgeJS/Sources/BridgeJSCore/Misc.swift | 110 +++++++++--------- .../Sources/BridgeJSTool/BridgeJSTool.swift | 24 +++- 2 files changed, 76 insertions(+), 58 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift index 70dae3a82..df6d0c755 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift @@ -1,12 +1,3 @@ -import class Foundation.FileHandle -import class Foundation.ProcessInfo -import func Foundation.open -import func Foundation.strerror -import var Foundation.errno -import var Foundation.O_WRONLY -import var Foundation.O_CREAT -import var Foundation.O_TRUNC - // MARK: - ProgressReporting public struct ProgressReporting { @@ -31,61 +22,66 @@ public struct ProgressReporting { // MARK: - Profiling -/// A simple time-profiler to emit `chrome://tracing` format +/// A simple time-profiler API public final class Profiling { nonisolated(unsafe) static var current: Profiling? - let startTime: ContinuousClock.Instant - let clock = ContinuousClock() - let output: @Sendable (String) -> Void - var firstEntry = true - - init(output: @Sendable @escaping (String) -> Void) { - self.startTime = ContinuousClock.now - self.output = output - } - - public static func with(body: @escaping () throws -> Void) rethrows -> Void { - guard let outputPath = ProcessInfo.processInfo.environment["BRIDGE_JS_PROFILING"] else { - return try body() + let beginEntry: (_ label: String) -> Void + let endEntry: (_ label: String) -> Void + let finalize: () -> Void + + /// Create a profiling instance that outputs Trace Event Format, which + /// can be viewed in chrome://tracing or other compatible viewers. + /// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit?usp=sharing + public static func traceEvent(output: @escaping (String) -> Void) -> Profiling { + let clock = ContinuousClock() + let startTime = clock.now + var firstEntry = true + + func formatTimestamp() -> Int { + let duration = startTime.duration(to: .now) + let (seconds, attoseconds) = duration.components + // Convert to microseconds + return Int(seconds * 1_000_000 + attoseconds / 1_000_000_000_000) } - let fd = open(outputPath, O_WRONLY | O_CREAT | O_TRUNC, 0o644) - guard fd >= 0 else { - let error = String(cString: strerror(errno)) - fatalError("Failed to open profiling output file \(outputPath): \(error)") - } - let output = FileHandle(fileDescriptor: fd, closeOnDealloc: true) - let profiling = Profiling(output: { output.write($0.data(using: .utf8) ?? Data()) }) - defer { - profiling.output("]\n") - } - Profiling.current = profiling - defer { - Profiling.current = nil - } - return try body() - } - private func formatTimestamp(instant: ContinuousClock.Instant) -> Int { - let duration = self.startTime.duration(to: instant) - let (seconds, attoseconds) = duration.components - // Convert to microseconds - return Int(seconds * 1_000_000 + attoseconds / 1_000_000_000_000) + return Profiling( + beginEntry: { label in + let entry = #"{"ph":"B","pid":1,"name":\#(JSON.serialize(label)),"ts":\#(formatTimestamp())}"# + if firstEntry { + firstEntry = false + output("[\n\(entry)") + } else { + output(",\n\(entry)") + } + }, + endEntry: { label in + output(#",\n{"ph":"E","pid":1,"name":\#(JSON.serialize(label)),"ts":\#(formatTimestamp())}"#) + }, + finalize: { + output("]\n") + } + ) } - func begin(_ label: String, _ instant: ContinuousClock.Instant) { - let entry = #"{"ph":"B","pid":1,"name":\#(JSON.serialize(label)),"ts":\#(formatTimestamp(instant: instant))}"# - if firstEntry { - firstEntry = false - output("[\n\(entry)") - } else { - output(",\n\(entry)") - } + public init( + beginEntry: @escaping (_ label: String) -> Void, + endEntry: @escaping (_ label: String) -> Void, + finalize: @escaping () -> Void + ) { + self.beginEntry = beginEntry + self.endEntry = endEntry + self.finalize = finalize } - func end(_ label: String, _ instant: ContinuousClock.Instant) { - let entry = #"{"ph":"E","pid":1,"name":\#(JSON.serialize(label)),"ts":\#(formatTimestamp(instant: instant))}"# - output(",\n\(entry)") + public static func with(_ makeCurrent: () -> Profiling?, body: @escaping () throws -> Void) rethrows -> Void { + guard let current = makeCurrent() else { + return try body() + } + defer { current.finalize() } + Profiling.current = current + defer { Profiling.current = nil } + return try body() } } @@ -94,9 +90,9 @@ public func withSpan(_ label: String, body: @escaping () throws -> T) rethrow guard let profiling = Profiling.current else { return try body() } - profiling.begin(label, profiling.clock.now) + profiling.beginEntry(label) defer { - profiling.end(label, profiling.clock.now) + profiling.endEntry(label) } return try body() } diff --git a/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift b/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift index f9fa56c42..b36b3ec8c 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift @@ -1,10 +1,17 @@ @preconcurrency import func Foundation.exit @preconcurrency import func Foundation.fputs +@preconcurrency import func Foundation.open +@preconcurrency import func Foundation.strerror @preconcurrency import var Foundation.stderr +@preconcurrency import var Foundation.errno +@preconcurrency import var Foundation.O_WRONLY +@preconcurrency import var Foundation.O_CREAT +@preconcurrency import var Foundation.O_TRUNC @preconcurrency import struct Foundation.URL @preconcurrency import struct Foundation.Data @preconcurrency import struct Foundation.ObjCBool @preconcurrency import class Foundation.JSONEncoder +@preconcurrency import class Foundation.FileHandle @preconcurrency import class Foundation.FileManager @preconcurrency import class Foundation.JSONDecoder @preconcurrency import class Foundation.ProcessInfo @@ -50,7 +57,7 @@ import BridgeJSUtilities static func main() throws { do { - try Profiling.with { + try Profiling.with(Profiling.make) { try run() } } catch { @@ -318,6 +325,21 @@ private func inputSwiftFiles(targetDirectory: URL, positionalArguments: [String] return positionalArguments } +extension Profiling { + static func make() -> Profiling? { + guard let outputPath = ProcessInfo.processInfo.environment["BRIDGE_JS_PROFILING"] else { + return nil + } + let fd = open(outputPath, O_WRONLY | O_CREAT | O_TRUNC, 0o644) + guard fd >= 0 else { + let error = String(cString: strerror(errno)) + fatalError("Failed to open profiling output file \(outputPath): \(error)") + } + let output = FileHandle(fileDescriptor: fd, closeOnDealloc: true) + return Profiling.traceEvent(output: { output.write($0.data(using: .utf8) ?? Data()) }) + } +} + // MARK: - Minimal Argument Parsing struct OptionRule { From 235a9bd99243d21612aefc398680a7d44a719fd0 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 9 Feb 2026 11:57:01 +0900 Subject: [PATCH 08/40] BridgeJS: Deduplicate closure signature collection logic (#605) Centralize the `BridgeType` traversal logic and use it to collect closure signatures in both `BridgeJSCore` and `BridgeJSLink`, removing redundant code. This is mostly NFC but added new closure signature collection paths for `.array` and `.dictionary` element types and for enums with associated values. --- .../Sources/BridgeJSCore/ClosureCodegen.swift | 102 +----------- .../Sources/BridgeJSLink/BridgeJSLink.swift | 82 +--------- .../BridgeJSSkeleton/BridgeJSSkeleton.swift | 146 ++++++++++++++++++ 3 files changed, 154 insertions(+), 176 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift index 3ec0418b3..49f2b99bf 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift @@ -8,27 +8,6 @@ import BridgeJSSkeleton public struct ClosureCodegen { public init() {} - func collectClosureSignatures(from parameters: [Parameter], into signatures: inout Set) { - for param in parameters { - collectClosureSignatures(from: param.type, into: &signatures) - } - } - - func collectClosureSignatures(from type: BridgeType, into signatures: inout Set) { - switch type { - case .closure(let signature, _): - signatures.insert(signature) - for paramType in signature.parameters { - collectClosureSignatures(from: paramType, into: &signatures) - } - collectClosureSignatures(from: signature.returnType, into: &signatures) - case .nullable(let wrapped, _): - collectClosureSignatures(from: wrapped, into: &signatures) - default: - break - } - } - func renderClosureHelpers(_ signature: ClosureSignature) throws -> [DeclSyntax] { let mangledName = signature.mangleName let helperName = "_BJS_Closure_\(mangledName)" @@ -242,83 +221,10 @@ public struct ClosureCodegen { } public func renderSupport(for skeleton: BridgeJSSkeleton) throws -> String? { - var closureSignatures: Set = [] - - if let exported = skeleton.exported { - for function in exported.functions { - collectClosureSignatures(from: function.parameters, into: &closureSignatures) - collectClosureSignatures(from: function.returnType, into: &closureSignatures) - } - for klass in exported.classes { - if let constructor = klass.constructor { - collectClosureSignatures(from: constructor.parameters, into: &closureSignatures) - } - for method in klass.methods { - collectClosureSignatures(from: method.parameters, into: &closureSignatures) - collectClosureSignatures(from: method.returnType, into: &closureSignatures) - } - for property in klass.properties { - collectClosureSignatures(from: property.type, into: &closureSignatures) - } - } - for proto in exported.protocols { - for method in proto.methods { - collectClosureSignatures(from: method.parameters, into: &closureSignatures) - collectClosureSignatures(from: method.returnType, into: &closureSignatures) - } - for property in proto.properties { - collectClosureSignatures(from: property.type, into: &closureSignatures) - } - } - for structDecl in exported.structs { - for property in structDecl.properties { - collectClosureSignatures(from: property.type, into: &closureSignatures) - } - if let constructor = structDecl.constructor { - collectClosureSignatures(from: constructor.parameters, into: &closureSignatures) - } - for method in structDecl.methods { - collectClosureSignatures(from: method.parameters, into: &closureSignatures) - collectClosureSignatures(from: method.returnType, into: &closureSignatures) - } - } - for enumDecl in exported.enums { - for method in enumDecl.staticMethods { - collectClosureSignatures(from: method.parameters, into: &closureSignatures) - collectClosureSignatures(from: method.returnType, into: &closureSignatures) - } - for property in enumDecl.staticProperties { - collectClosureSignatures(from: property.type, into: &closureSignatures) - } - } - } - - if let imported = skeleton.imported { - for fileSkeleton in imported.children { - for getter in fileSkeleton.globalGetters { - collectClosureSignatures(from: getter.type, into: &closureSignatures) - } - for function in fileSkeleton.functions { - collectClosureSignatures(from: function.parameters, into: &closureSignatures) - collectClosureSignatures(from: function.returnType, into: &closureSignatures) - } - for type in fileSkeleton.types { - if let constructor = type.constructor { - collectClosureSignatures(from: constructor.parameters, into: &closureSignatures) - } - for getter in type.getters { - collectClosureSignatures(from: getter.type, into: &closureSignatures) - } - for setter in type.setters { - collectClosureSignatures(from: setter.type, into: &closureSignatures) - } - for method in type.methods + type.staticMethods { - collectClosureSignatures(from: method.parameters, into: &closureSignatures) - collectClosureSignatures(from: method.returnType, into: &closureSignatures) - } - } - } - } + let collector = ClosureSignatureCollectorVisitor() + var walker = BridgeTypeWalker(visitor: collector) + walker.walk(skeleton) + let closureSignatures = walker.visitor.signatures guard !closureSignatures.isEmpty else { return nil } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index 13ea4e910..621e9c98b 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -610,13 +610,10 @@ public struct BridgeJSLink { for unified in skeletons { let moduleName = unified.moduleName - var closureSignatures: Set = [] - if let exported = unified.exported { - collectClosureSignatures(from: exported, into: &closureSignatures) - } - if let imported = unified.imported { - collectClosureSignatures(from: imported, into: &closureSignatures) - } + let collector = ClosureSignatureCollectorVisitor() + var walker = BridgeTypeWalker(visitor: collector) + walker.walk(unified) + let closureSignatures = walker.visitor.signatures guard !closureSignatures.isEmpty else { continue } @@ -714,77 +711,6 @@ public struct BridgeJSLink { return printer } - private func collectClosureSignatures(from skeleton: ExportedSkeleton, into signatures: inout Set) - { - for function in skeleton.functions { - collectClosureSignatures(from: function.parameters, into: &signatures) - collectClosureSignatures(from: function.returnType, into: &signatures) - } - for klass in skeleton.classes { - if let constructor = klass.constructor { - collectClosureSignatures(from: constructor.parameters, into: &signatures) - } - for method in klass.methods { - collectClosureSignatures(from: method.parameters, into: &signatures) - collectClosureSignatures(from: method.returnType, into: &signatures) - } - for property in klass.properties { - collectClosureSignatures(from: property.type, into: &signatures) - } - } - } - - private func collectClosureSignatures( - from skeleton: ImportedModuleSkeleton, - into signatures: inout Set - ) { - for fileSkeleton in skeleton.children { - for getter in fileSkeleton.globalGetters { - collectClosureSignatures(from: getter.type, into: &signatures) - } - for function in fileSkeleton.functions { - collectClosureSignatures(from: function.parameters, into: &signatures) - collectClosureSignatures(from: function.returnType, into: &signatures) - } - for type in fileSkeleton.types { - if let constructor = type.constructor { - collectClosureSignatures(from: constructor.parameters, into: &signatures) - } - for getter in type.getters { - collectClosureSignatures(from: getter.type, into: &signatures) - } - for setter in type.setters { - collectClosureSignatures(from: setter.type, into: &signatures) - } - for method in type.methods + type.staticMethods { - collectClosureSignatures(from: method.parameters, into: &signatures) - collectClosureSignatures(from: method.returnType, into: &signatures) - } - } - } - } - - private func collectClosureSignatures(from parameters: [Parameter], into signatures: inout Set) { - for param in parameters { - collectClosureSignatures(from: param.type, into: &signatures) - } - } - - private func collectClosureSignatures(from type: BridgeType, into signatures: inout Set) { - switch type { - case .closure(let signature, _): - signatures.insert(signature) - for paramType in signature.parameters { - collectClosureSignatures(from: paramType, into: &signatures) - } - collectClosureSignatures(from: signature.returnType, into: &signatures) - case .nullable(let wrapped, _): - collectClosureSignatures(from: wrapped, into: &signatures) - default: - break - } - } - private func generateInvokeFunction( signature: ClosureSignature, functionName: String diff --git a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift index 3ebc91306..ba25b6ff9 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift @@ -247,6 +247,138 @@ public struct Parameter: Codable, Equatable, Sendable { } } +// MARK: - BridgeType Visitor + +public protocol BridgeTypeVisitor { + mutating func visitClosure(_ signature: ClosureSignature, useJSTypedClosure: Bool) +} + +public struct BridgeTypeWalker { + public var visitor: Visitor + + public init(visitor: Visitor) { + self.visitor = visitor + } + + public mutating func walk(_ type: BridgeType) { + switch type { + case .closure(let signature, let useJSTypedClosure): + visitor.visitClosure(signature, useJSTypedClosure: useJSTypedClosure) + for paramType in signature.parameters { + walk(paramType) + } + walk(signature.returnType) + case .nullable(let wrapped, _): + walk(wrapped) + case .array(let element): + walk(element) + case .dictionary(let value): + walk(value) + default: + break + } + } + public mutating func walk(_ parameters: [Parameter]) { + for param in parameters { + walk(param.type) + } + } + public mutating func walk(_ function: ExportedFunction) { + walk(function.parameters) + walk(function.returnType) + } + public mutating func walk(_ constructor: ExportedConstructor) { + walk(constructor.parameters) + } + public mutating func walk(_ skeleton: ExportedSkeleton) { + for function in skeleton.functions { + walk(function) + } + for klass in skeleton.classes { + if let constructor = klass.constructor { + walk(constructor.parameters) + } + for method in klass.methods { + walk(method) + } + for property in klass.properties { + walk(property.type) + } + } + for proto in skeleton.protocols { + for method in proto.methods { + walk(method) + } + for property in proto.properties { + walk(property.type) + } + } + for structDecl in skeleton.structs { + for property in structDecl.properties { + walk(property.type) + } + if let constructor = structDecl.constructor { + walk(constructor.parameters) + } + for method in structDecl.methods { + walk(method) + } + } + for enumDecl in skeleton.enums { + for enumCase in enumDecl.cases { + for associatedValue in enumCase.associatedValues { + walk(associatedValue.type) + } + } + for method in enumDecl.staticMethods { + walk(method) + } + for property in enumDecl.staticProperties { + walk(property.type) + } + } + } + public mutating func walk(_ function: ImportedFunctionSkeleton) { + walk(function.parameters) + walk(function.returnType) + } + public mutating func walk(_ skeleton: ImportedModuleSkeleton) { + for fileSkeleton in skeleton.children { + for getter in fileSkeleton.globalGetters { + walk(getter.type) + } + for setter in fileSkeleton.globalSetters { + walk(setter.type) + } + for function in fileSkeleton.functions { + walk(function) + } + for type in fileSkeleton.types { + if let constructor = type.constructor { + walk(constructor.parameters) + } + for getter in type.getters { + walk(getter.type) + } + for setter in type.setters { + walk(setter.type) + } + for method in type.methods + type.staticMethods { + walk(method) + } + } + } + } + public mutating func walk(_ skeleton: BridgeJSSkeleton) { + if let exported = skeleton.exported { + walk(exported) + } + if let imported = skeleton.imported { + walk(imported) + } + } +} + public struct Effects: Codable, Equatable, Sendable { public var isAsync: Bool public var isThrows: Bool @@ -873,6 +1005,20 @@ public struct ImportedModuleSkeleton: Codable { } } +// MARK: - Closure signature collection visitor + +public struct ClosureSignatureCollectorVisitor: BridgeTypeVisitor { + public var signatures: Set = [] + + public init(signatures: Set = []) { + self.signatures = signatures + } + + public mutating func visitClosure(_ signature: ClosureSignature, useJSTypedClosure: Bool) { + signatures.insert(signature) + } +} + // MARK: - Unified Skeleton /// Unified skeleton containing both exported and imported API definitions From 3bc0400b3627ca9bc3e2e3fca7d604eef2b9985a Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 9 Feb 2026 11:19:50 +0900 Subject: [PATCH 09/40] [NFC] BridgeJS: Move CodeFragmentPrintetr to BridgeJSCore So that we can use it for Swift code generation --- .../BridgeJSLink/CodeFragmentPrinter.swift | 80 ------------------- .../Sources/BridgeJSLink/JSGlueGen.swift | 3 + .../BridgeJSLink/JSIntrinsicRegistry.swift | 37 +++++++++ .../Sources/BridgeJSUtilities/Utilities.swift | 47 +++++++++++ 4 files changed, 87 insertions(+), 80 deletions(-) delete mode 100644 Plugins/BridgeJS/Sources/BridgeJSLink/CodeFragmentPrinter.swift create mode 100644 Plugins/BridgeJS/Sources/BridgeJSLink/JSIntrinsicRegistry.swift diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/CodeFragmentPrinter.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/CodeFragmentPrinter.swift deleted file mode 100644 index 4bad3dd34..000000000 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/CodeFragmentPrinter.swift +++ /dev/null @@ -1,80 +0,0 @@ -/// Registry for JS helper intrinsics used during code generation. -final class JSIntrinsicRegistry { - private var entries: [String: [String]] = [:] - - var isEmpty: Bool { - entries.isEmpty - } - - func register(name: String, build: (CodeFragmentPrinter) throws -> Void) rethrows { - guard entries[name] == nil else { return } - let printer = CodeFragmentPrinter() - try build(printer) - entries[name] = printer.lines - } - - func reset() { - entries.removeAll() - } - - func emitLines() -> [String] { - var emitted: [String] = [] - for key in entries.keys.sorted() { - if let lines = entries[key] { - emitted.append(contentsOf: lines) - emitted.append("") - } - } - if emitted.last == "" { - emitted.removeLast() - } - return emitted - } -} - -/// 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) { - if line.isEmpty { - // Empty lines should not have trailing spaces - lines.append("") - return - } - 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 index 9402cdd9d..7928f480d 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -1,6 +1,9 @@ #if canImport(BridgeJSSkeleton) import BridgeJSSkeleton #endif +#if canImport(BridgeJSUtilities) +import BridgeJSUtilities +#endif /// A scope for variables for JS glue code final class JSGlueVariableScope { diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSIntrinsicRegistry.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSIntrinsicRegistry.swift new file mode 100644 index 000000000..c3e77d83f --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSIntrinsicRegistry.swift @@ -0,0 +1,37 @@ +#if canImport(BridgeJSUtilities) +import BridgeJSUtilities +#endif + +/// Registry for JS helper intrinsics used during code generation. +final class JSIntrinsicRegistry { + private var entries: [String: [String]] = [:] + + var isEmpty: Bool { + entries.isEmpty + } + + func register(name: String, build: (CodeFragmentPrinter) throws -> Void) rethrows { + guard entries[name] == nil else { return } + let printer = CodeFragmentPrinter() + try build(printer) + entries[name] = printer.lines + } + + func reset() { + entries.removeAll() + } + + func emitLines() -> [String] { + var emitted: [String] = [] + for key in entries.keys.sorted() { + if let lines = entries[key] { + emitted.append(contentsOf: lines) + emitted.append("") + } + } + if emitted.last == "" { + emitted.removeLast() + } + return emitted + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift b/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift index 2791aa5be..ed6fa04f0 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift @@ -27,3 +27,50 @@ public enum BridgeJSGeneratedFile { """ } } + +/// A printer for code fragments. +public final class CodeFragmentPrinter { + public private(set) var lines: [String] = [] + private var indentLevel: Int = 0 + + public init(header: String = "") { + self.lines.append(contentsOf: header.split(separator: "\n").map { String($0) }) + } + + public func nextLine() { + lines.append("") + } + + public func write(_ line: S) { + if line.isEmpty { + // Empty lines should not have trailing spaces + lines.append("") + return + } + lines.append(String(repeating: " ", count: indentLevel * 4) + String(line)) + } + + public func write(lines: [String]) { + for line in lines { + write(line) + } + } + + public func write(contentsOf printer: CodeFragmentPrinter) { + self.write(lines: printer.lines) + } + + public func indent() { + indentLevel += 1 + } + + public func unindent() { + indentLevel -= 1 + } + + public func indent(_ body: () throws -> Void) rethrows { + indentLevel += 1 + try body() + indentLevel -= 1 + } +} From 2e4de4fe08d5be9a1b7617de6c9287f3c6f76255 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 9 Feb 2026 12:48:00 +0900 Subject: [PATCH 10/40] BridgeJS: Explicitly reject unsupported optional wrapped types --- Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 9402cdd9d..3205388e4 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -1230,7 +1230,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("}") scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) default: - () + throw BridgeJSLinkError(message: "Unsupported wrapped type for returning from JS function: \(wrappedType)") } return [] From 8f77619d802c83abc0a0531ddaab705c39ebdd71 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 9 Feb 2026 12:56:35 +0900 Subject: [PATCH 11/40] BridgeJS: Fix handling of optional Swift heap objects in JS glue generation --- .../Sources/BridgeJSLink/JSGlueGen.swift | 2 ++ .../Inputs/MacroSwift/SwiftClass.swift | 1 + .../BridgeJSCodegenTests/SwiftClass.json | 28 +++++++++++++++++++ .../BridgeJSCodegenTests/SwiftClass.swift | 18 ++++++++++++ .../BridgeJSLinkTests/Protocol.js | 1 + .../BridgeJSLinkTests/SwiftClass.d.ts | 1 + .../BridgeJSLinkTests/SwiftClass.js | 9 ++++++ .../Generated/BridgeJS.swift | 18 ++++++++++++ .../Generated/JavaScript/BridgeJS.json | 28 +++++++++++++++++++ .../JavaScript/SwiftClassSupportTests.mjs | 3 ++ .../SwiftClassSupportTests.swift | 9 ++++++ 11 files changed, 118 insertions(+) diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 3205388e4..c502513d4 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -1120,6 +1120,8 @@ struct IntrinsicJSFragment: Sendable { scope.emitPushF64Parameter(payload2Var, printer: printer) } scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + case .swiftHeapObject: + printer.write("return \(isSomeVar) ? \(value).pointer : 0;") case .array(let elementType): printer.write("if (\(isSomeVar)) {") try printer.indent { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClass.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClass.swift index aa520783a..2b41d91d6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClass.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClass.swift @@ -20,3 +20,4 @@ @JS package class PackageGreeter {} @JSFunction func jsRoundTripGreeter(greeter: Greeter) throws(JSException) -> Greeter +@JSFunction func jsRoundTripOptionalGreeter(greeter: Greeter?) throws(JSException) -> Greeter? \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.json index d1bf42cff..7cebdd5e6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.json @@ -162,6 +162,34 @@ "_0" : "Greeter" } } + }, + { + "name" : "jsRoundTripOptionalGreeter", + "parameters" : [ + { + "name" : "greeter", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } } ], "types" : [ diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.swift index 581d6f1c0..ca82b87c4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.swift @@ -152,4 +152,22 @@ func _$jsRoundTripGreeter(_ greeter: Greeter) throws(JSException) -> Greeter { throw error } return Greeter.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_jsRoundTripOptionalGreeter") +fileprivate func bjs_jsRoundTripOptionalGreeter(_ greeterIsSome: Int32, _ greeterPointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer +#else +fileprivate func bjs_jsRoundTripOptionalGreeter(_ greeterIsSome: Int32, _ greeterPointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripOptionalGreeter(_ greeter: Optional) throws(JSException) -> Optional { + let (greeterIsSome, greeterPointer) = greeter.bridgeJSLowerParameter() + let ret = bjs_jsRoundTripOptionalGreeter(greeterIsSome, greeterPointer) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturn(ret) } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js index 00b9626e3..4d9f3e0bb 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js @@ -538,6 +538,7 @@ export async function createInstantiator(options, swift) { try { let ret = swift.memory.getObject(self).createOptionalHelper(); const isSome = ret != null; + return isSome ? ret.pointer : 0; } catch (error) { setException(error); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.d.ts index d3461f8c1..05fc97fee 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.d.ts @@ -32,6 +32,7 @@ export type Exports = { } export type Imports = { jsRoundTripGreeter(greeter: Greeter): Greeter; + jsRoundTripOptionalGreeter(greeter: Greeter | null): Greeter | null; } export function createInstantiator(options: { imports: Imports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js index eaa5d7720..85d423f8a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js @@ -225,6 +225,15 @@ export async function createInstantiator(options, swift) { return 0 } } + TestModule["bjs_jsRoundTripOptionalGreeter"] = function bjs_jsRoundTripOptionalGreeter(greeterIsSome, greeterWrappedValue) { + try { + let ret = imports.jsRoundTripOptionalGreeter(greeterIsSome ? Greeter.__construct(greeterWrappedValue) : null); + const isSome = ret != null; + return isSome ? ret.pointer : 0; + } catch (error) { + setException(error); + } + } }, setInstance: (i) => { instance = i; diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index 1feb3eed6..b10a82fdf 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -10677,6 +10677,15 @@ fileprivate func bjs_SwiftClassSupportImports_jsRoundTripGreeter_static(_ greete } #endif +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_SwiftClassSupportImports_jsRoundTripOptionalGreeter_static") +fileprivate func bjs_SwiftClassSupportImports_jsRoundTripOptionalGreeter_static(_ greeterIsSome: Int32, _ greeterPointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer +#else +fileprivate func bjs_SwiftClassSupportImports_jsRoundTripOptionalGreeter_static(_ greeterIsSome: Int32, _ greeterPointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + fatalError("Only available on WebAssembly") +} +#endif + func _$SwiftClassSupportImports_jsRoundTripGreeter(_ greeter: Greeter) throws(JSException) -> Greeter { let greeterPointer = greeter.bridgeJSLowerParameter() let ret = bjs_SwiftClassSupportImports_jsRoundTripGreeter_static(greeterPointer) @@ -10684,4 +10693,13 @@ func _$SwiftClassSupportImports_jsRoundTripGreeter(_ greeter: Greeter) throws(JS throw error } return Greeter.bridgeJSLiftReturn(ret) +} + +func _$SwiftClassSupportImports_jsRoundTripOptionalGreeter(_ greeter: Optional) throws(JSException) -> Optional { + let (greeterIsSome, greeterPointer) = greeter.bridgeJSLowerParameter() + let ret = bjs_SwiftClassSupportImports_jsRoundTripOptionalGreeter_static(greeterIsSome, greeterPointer) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturn(ret) } \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json index de7ab4a5d..7e2d4d855 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json @@ -15345,6 +15345,34 @@ "_0" : "Greeter" } } + }, + { + "name" : "jsRoundTripOptionalGreeter", + "parameters" : [ + { + "name" : "greeter", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } } ] } diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs index fdb5d498d..0368cb74a 100644 --- a/Tests/BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs +++ b/Tests/BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs @@ -6,5 +6,8 @@ export function getImports(importsContext) { jsRoundTripGreeter: (greeter) => { return greeter; }, + jsRoundTripOptionalGreeter: (greeter) => { + return greeter; + }, }; } \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift b/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift index 3cee17554..1a3dd0a4f 100644 --- a/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift +++ b/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift @@ -3,6 +3,7 @@ import XCTest @JSClass struct SwiftClassSupportImports { @JSFunction static func jsRoundTripGreeter(_ greeter: Greeter) throws(JSException) -> Greeter + @JSFunction static func jsRoundTripOptionalGreeter(_ greeter: Greeter?) throws(JSException) -> Greeter? } final class SwiftClassSupportTests: XCTestCase { @@ -10,4 +11,12 @@ final class SwiftClassSupportTests: XCTestCase { let greeter = try SwiftClassSupportImports.jsRoundTripGreeter(Greeter(name: "Hello")) XCTAssertEqual(greeter.name, "Hello") } + + func testRoundTripOptionalGreeter() throws { + let greeter1 = try SwiftClassSupportImports.jsRoundTripOptionalGreeter(nil) + XCTAssertNil(greeter1) + + let greeter2 = try SwiftClassSupportImports.jsRoundTripOptionalGreeter(Greeter(name: "Hello")) + XCTAssertEqual(greeter2?.name, "Hello") + } } From 4c0a345b09923faa97ae280a2140830a01cbd1ad Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 9 Feb 2026 12:58:39 +0900 Subject: [PATCH 12/40] BridgeJS: Fix optional Swift heap object for parameter lifting in JS glue --- Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift | 6 ++++-- .../BridgeJSToolTests/Inputs/MacroSwift/SwiftClass.swift | 2 +- .../__Snapshots__/BridgeJSLinkTests/Protocol.js | 2 +- .../__Snapshots__/BridgeJSLinkTests/SwiftClass.js | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index c502513d4..db900cf99 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -668,7 +668,7 @@ struct IntrinsicJSFragment: Sendable { resultExpr = "\(isSome) ? \(JSGlueVariableScope.reservedSwift).memory.getObject(\(wrappedValue)) : \(absenceLiteral)" case .swiftHeapObject(let name): - resultExpr = "\(isSome) ? \(name).__construct(\(wrappedValue)) : \(absenceLiteral)" + resultExpr = "\(isSome) ? _exports['\(name)'].__construct(\(wrappedValue)) : \(absenceLiteral)" case .jsObject: resultExpr = "\(isSome) ? \(JSGlueVariableScope.reservedSwift).memory.getObject(\(wrappedValue)) : \(absenceLiteral)" @@ -1232,7 +1232,9 @@ struct IntrinsicJSFragment: Sendable { printer.write("}") scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) default: - throw BridgeJSLinkError(message: "Unsupported wrapped type for returning from JS function: \(wrappedType)") + throw BridgeJSLinkError( + message: "Unsupported wrapped type for returning from JS function: \(wrappedType)" + ) } return [] diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClass.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClass.swift index 2b41d91d6..d7b5a5b8e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClass.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClass.swift @@ -20,4 +20,4 @@ @JS package class PackageGreeter {} @JSFunction func jsRoundTripGreeter(greeter: Greeter) throws(JSException) -> Greeter -@JSFunction func jsRoundTripOptionalGreeter(greeter: Greeter?) throws(JSException) -> Greeter? \ No newline at end of file +@JSFunction func jsRoundTripOptionalGreeter(greeter: Greeter?) throws(JSException) -> Greeter? diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js index 4d9f3e0bb..fd37c7178 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js @@ -529,7 +529,7 @@ export async function createInstantiator(options, swift) { } TestModule["bjs_MyViewControllerDelegate_onOptionalHelperUpdated"] = function bjs_MyViewControllerDelegate_onOptionalHelperUpdated(self, helperIsSome, helperWrappedValue) { try { - swift.memory.getObject(self).onOptionalHelperUpdated(helperIsSome ? Helper.__construct(helperWrappedValue) : null); + swift.memory.getObject(self).onOptionalHelperUpdated(helperIsSome ? _exports['Helper'].__construct(helperWrappedValue) : null); } catch (error) { setException(error); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js index 85d423f8a..13ea6ba75 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js @@ -227,7 +227,7 @@ export async function createInstantiator(options, swift) { } TestModule["bjs_jsRoundTripOptionalGreeter"] = function bjs_jsRoundTripOptionalGreeter(greeterIsSome, greeterWrappedValue) { try { - let ret = imports.jsRoundTripOptionalGreeter(greeterIsSome ? Greeter.__construct(greeterWrappedValue) : null); + let ret = imports.jsRoundTripOptionalGreeter(greeterIsSome ? _exports['Greeter'].__construct(greeterWrappedValue) : null); const isSome = ret != null; return isSome ? ret.pointer : 0; } catch (error) { From c74f65991b4dfdc2e8f8b07d4284a50730abe543 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 9 Feb 2026 18:16:19 +0900 Subject: [PATCH 13/40] BridgeJS: Fix missing escape in profiling output --- Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift index df6d0c755..67f5170c4 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift @@ -56,7 +56,7 @@ public final class Profiling { } }, endEntry: { label in - output(#",\n{"ph":"E","pid":1,"name":\#(JSON.serialize(label)),"ts":\#(formatTimestamp())}"#) + output(#",\#n{"ph":"E","pid":1,"name":\#(JSON.serialize(label)),"ts":\#(formatTimestamp())}"#) }, finalize: { output("]\n") From a0b8448a1ffadaaa75e78d0092dc7307783ff2b5 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 9 Feb 2026 19:40:36 +0900 Subject: [PATCH 14/40] BridgeJS: Add `IntrinsicJSFragment.PrintCodeContext` Prepare to extend the context more --- .../Sources/BridgeJSLink/BridgeJSLink.swift | 79 ++- .../Sources/BridgeJSLink/JSGlueGen.swift | 645 +++++++++++------- 2 files changed, 468 insertions(+), 256 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index 2695d9861..7e6ce9b55 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -717,8 +717,11 @@ public struct BridgeJSLink { functionName: String ) throws -> [String] { let printer = CodeFragmentPrinter() - let scope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) - let cleanupCode = CodeFragmentPrinter() + let context = IntrinsicJSFragment.PrintCodeContext( + scope: JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry), + printer: printer, + cleanupCode: CodeFragmentPrinter() + ) // Build parameter list for invoke function var invokeParams: [String] = ["callbackId"] @@ -746,7 +749,7 @@ public struct BridgeJSLink { } else { args = ["param\(index)Id", "param\(index)"] } - _ = try fragment.printCode(args, scope, printer, cleanupCode) + _ = try fragment.printCode(args, context) } let callbackParams = signature.parameters.indices.map { "param\($0)" }.joined(separator: ", ") @@ -765,13 +768,13 @@ public struct BridgeJSLink { } let returnFragment = try IntrinsicJSFragment.closureLowerReturn(type: signature.returnType) - _ = try returnFragment.printCode(["result"], scope, printer, cleanupCode) + _ = try returnFragment.printCode(["result"], context) } printer.write("} catch (error) {") try printer.indent { printer.write("\(JSGlueVariableScope.reservedSetException)?.(error);") let errorFragment = IntrinsicJSFragment.closureErrorReturn(type: signature.returnType) - _ = try errorFragment.printCode([], scope, printer, cleanupCode) + _ = try errorFragment.printCode([], context) } printer.write("}") } @@ -786,8 +789,11 @@ public struct BridgeJSLink { functionName: String ) throws -> [String] { let printer = CodeFragmentPrinter() - let scope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) - let cleanupCode = CodeFragmentPrinter() + let context = IntrinsicJSFragment.PrintCodeContext( + scope: JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry), + printer: printer, + cleanupCode: CodeFragmentPrinter() + ) printer.write( "const \(functionName) = function(\(signature.parameters.indices.map { "param\($0)" }.joined(separator: ", "))) {" @@ -798,7 +804,7 @@ public struct BridgeJSLink { for (index, paramType) in signature.parameters.enumerated() { let paramName = "param\(index)" let fragment = try IntrinsicJSFragment.lowerParameter(type: paramType) - let lowered = try fragment.printCode([paramName], scope, printer, cleanupCode) + let lowered = try fragment.printCode([paramName], context) invokeArgs.append(contentsOf: lowered) } @@ -822,7 +828,7 @@ public struct BridgeJSLink { printer.write("}") let returnFragment = try IntrinsicJSFragment.closureLiftReturn(type: signature.returnType) - _ = try returnFragment.printCode([invokeResultName], scope, printer, cleanupCode) + _ = try returnFragment.printCode([invokeResultName], context) } printer.write("};") @@ -1010,7 +1016,14 @@ public struct BridgeJSLink { let structScope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) let structCleanup = CodeFragmentPrinter() let fragment = IntrinsicJSFragment.structHelper(structDefinition: structDef, allStructs: allStructs) - _ = try fragment.printCode([structDef.name], structScope, structPrinter, structCleanup) + _ = try fragment.printCode( + [structDef.name], + IntrinsicJSFragment.PrintCodeContext( + scope: structScope, + printer: structPrinter, + cleanupCode: structCleanup + ) + ) bodyPrinter.write(lines: structPrinter.lines) } @@ -1022,7 +1035,14 @@ public struct BridgeJSLink { let enumScope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) let enumCleanup = CodeFragmentPrinter() let fragment = IntrinsicJSFragment.associatedValueEnumHelperFactory(enumDefinition: enumDef) - _ = try fragment.printCode([enumDef.valuesName], enumScope, enumPrinter, enumCleanup) + _ = try fragment.printCode( + [enumDef.valuesName], + IntrinsicJSFragment.PrintCodeContext( + scope: enumScope, + printer: enumPrinter, + cleanupCode: enumCleanup + ) + ) bodyPrinter.write(lines: enumPrinter.lines) } bodyPrinter.nextLine() @@ -1269,12 +1289,18 @@ public struct BridgeJSLink { var parameterForwardings: [String] = [] let effects: Effects let scope: JSGlueVariableScope + let context: IntrinsicJSFragment.PrintCodeContext init(effects: Effects, intrinsicRegistry: JSIntrinsicRegistry) { self.effects = effects self.scope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) self.body = CodeFragmentPrinter() self.cleanupCode = CodeFragmentPrinter() + self.context = IntrinsicJSFragment.PrintCodeContext( + scope: scope, + printer: body, + cleanupCode: cleanupCode + ) } func lowerParameter(param: Parameter) throws { @@ -1283,7 +1309,7 @@ public struct BridgeJSLink { loweringFragment.parameters.count == 1, "Lowering fragment should have exactly one parameter to lower" ) - let loweredValues = try loweringFragment.printCode([param.name], scope, body, cleanupCode) + let loweredValues = try loweringFragment.printCode([param.name], context) parameterForwardings.append(contentsOf: loweredValues) } @@ -1315,7 +1341,7 @@ public struct BridgeJSLink { body.write("const \(returnVariable) = \(call);") fragmentArguments = [returnVariable] } - let liftedValues = try liftingFragment.printCode(fragmentArguments, scope, body, cleanupCode) + let liftedValues = try liftingFragment.printCode(fragmentArguments, context) assert(liftedValues.count <= 1, "Lifting fragment should produce at most one value") return liftedValues.first } @@ -1566,14 +1592,18 @@ public struct BridgeJSLink { var jsTopLevelLines: [String] = [] var dtsTypeLines: [String] = [] let scope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) - let cleanup = CodeFragmentPrinter() let printer = CodeFragmentPrinter() + let context = IntrinsicJSFragment.PrintCodeContext( + scope: scope, + printer: printer, + cleanupCode: CodeFragmentPrinter() + ) let enumValuesName = enumDefinition.valuesName switch enumDefinition.enumType { case .simple: let fragment = IntrinsicJSFragment.simpleEnumHelper(enumDefinition: enumDefinition) - _ = try fragment.printCode([enumValuesName], scope, printer, cleanup) + _ = try fragment.printCode([enumValuesName], context) jsTopLevelLines.append(contentsOf: printer.lines) case .rawValue: guard enumDefinition.rawType != nil else { @@ -1581,11 +1611,11 @@ public struct BridgeJSLink { } let fragment = IntrinsicJSFragment.rawValueEnumHelper(enumDefinition: enumDefinition) - _ = try fragment.printCode([enumValuesName], scope, printer, cleanup) + _ = try fragment.printCode([enumValuesName], context) jsTopLevelLines.append(contentsOf: printer.lines) case .associatedValue: let fragment = IntrinsicJSFragment.associatedValueEnumValues(enumDefinition: enumDefinition) - _ = try fragment.printCode([enumValuesName], scope, printer, cleanup) + _ = try fragment.printCode([enumValuesName], context) jsTopLevelLines.append(contentsOf: printer.lines) case .namespace: break @@ -2155,12 +2185,18 @@ extension BridgeJSLink { let context: BridgeContext var parameterNames: [String] = [] var parameterForwardings: [String] = [] + let printContext: IntrinsicJSFragment.PrintCodeContext init(context: BridgeContext = .importTS, intrinsicRegistry: JSIntrinsicRegistry) { self.body = CodeFragmentPrinter() self.scope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) self.cleanupCode = CodeFragmentPrinter() self.context = context + self.printContext = IntrinsicJSFragment.PrintCodeContext( + scope: scope, + printer: body, + cleanupCode: cleanupCode + ) } func liftSelf() { @@ -2179,7 +2215,7 @@ extension BridgeJSLink { valuesToLift = liftingFragment.parameters.map { scope.variable(param.name + $0.capitalizedFirstLetter) } parameterNames.append(contentsOf: valuesToLift) } - let liftedValues = try liftingFragment.printCode(valuesToLift, scope, body, cleanupCode) + let liftedValues = try liftingFragment.printCode(valuesToLift, printContext) assert(liftedValues.count == 1, "Lifting fragment should produce exactly one value") parameterForwardings.append(contentsOf: liftedValues) } @@ -2289,7 +2325,7 @@ extension BridgeJSLink { ) let fragment = try IntrinsicJSFragment.protocolPropertyOptionalToSideChannel(wrappedType: wrappedType) - _ = try fragment.printCode([resultVar], scope, body, cleanupCode) + _ = try fragment.printCode([resultVar], printContext) return nil // Side-channel types return nil (no direct return value) } @@ -2342,7 +2378,10 @@ extension BridgeJSLink { loweringFragment: IntrinsicJSFragment ) throws -> String? { assert(loweringFragment.parameters.count <= 1, "Lowering fragment should have at most one parameter") - let loweredValues = try loweringFragment.printCode(returnExpr.map { [$0] } ?? [], scope, body, cleanupCode) + let loweredValues = try loweringFragment.printCode( + returnExpr.map { [$0] } ?? [], + printContext + ) assert(loweredValues.count <= 1, "Lowering fragment should produce at most one value") return loweredValues.first } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 6e1ead728..c60cc2dbf 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -146,31 +146,54 @@ extension JSGlueVariableScope { /// /// See `BridgeJSIntrinsics.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. + struct PrintCodeContext { + /// The scope of the variables. + var scope: JSGlueVariableScope + /// The printer to print the main fragment code. + var printer: CodeFragmentPrinter + /// The printer to print the code that is expected to be executed at the end of the caller of the fragment. + var cleanupCode: CodeFragmentPrinter + + func with(_ keyPath: WritableKeyPath, _ value: T) -> PrintCodeContext { + var new = self + new[keyPath: keyPath] = value + return new + } + } + + /// A function that 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. + /// - context: The context of the printing. /// - Returns: List of result expressions. - let printCode: + typealias PrintCode = @Sendable ( _ arguments: [String], - _ scope: JSGlueVariableScope, - _ printer: CodeFragmentPrinter, - _ cleanupCode: CodeFragmentPrinter + _ context: PrintCodeContext ) throws -> [String] + /// The names of the parameters that the fragment expects. + let parameters: [String] + + /// Prints the fragment code. + let printCode: PrintCode + + init(parameters: [String], printCode: @escaping PrintCode) { + self.parameters = parameters + self.printCode = printCode + } + + func printCode(_ arguments: [String], _ context: PrintCodeContext) throws -> [String] { + return try printCode(arguments, context) + } + /// A fragment that does nothing static let void = IntrinsicJSFragment( parameters: [], - printCode: { _, _, _, _ in + printCode: { _, _ in return [] } ) @@ -178,7 +201,7 @@ struct IntrinsicJSFragment: Sendable { /// A fragment that returns the argument as is. static let identity = IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, _ in return [arguments[0]] } ) @@ -188,19 +211,19 @@ struct IntrinsicJSFragment: Sendable { static let boolLowerParameter = identity static let boolLiftReturn = IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, _ in return ["\(arguments[0]) !== 0"] } ) static let boolLiftParameter = IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, _ in return ["\(arguments[0]) !== 0"] } ) static let boolLowerReturn = IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, _ in return ["\(arguments[0]) ? 1 : 0"] } ) @@ -208,7 +231,7 @@ struct IntrinsicJSFragment: Sendable { /// Convert signed Int32 to unsigned for UInt values static let uintLiftReturn = IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, _ in return ["\(arguments[0]) >>> 0"] } ) @@ -216,7 +239,8 @@ struct IntrinsicJSFragment: Sendable { static let stringLowerParameter = IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) let argument = arguments[0] let bytesLabel = scope.variable("\(argument)Bytes") let bytesIdLabel = scope.variable("\(argument)Id") @@ -228,7 +252,8 @@ struct IntrinsicJSFragment: Sendable { ) static let stringLiftReturn = IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) let resultLabel = scope.variable("ret") printer.write("const \(resultLabel) = \(JSGlueVariableScope.reservedStorageToReturnString);") printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") @@ -237,7 +262,8 @@ struct IntrinsicJSFragment: Sendable { ) static let stringLiftParameter = IntrinsicJSFragment( parameters: ["objectId"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) let objectId = arguments[0] let objectLabel = scope.variable("\(objectId)Object") // TODO: Implement "take" operation @@ -248,7 +274,8 @@ struct IntrinsicJSFragment: Sendable { ) static let stringLowerReturn = IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) printer.write( "\(JSGlueVariableScope.reservedStorageToReturnBytes) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(arguments[0]));" ) @@ -258,13 +285,14 @@ struct IntrinsicJSFragment: Sendable { static let jsObjectLowerParameter = IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, _ in return ["swift.memory.retain(\(arguments[0]))"] } ) static let jsObjectLiftReturn = IntrinsicJSFragment( parameters: ["retId"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) // TODO: Implement "take" operation let resultLabel = scope.variable("ret") let retId = arguments[0] @@ -275,7 +303,8 @@ struct IntrinsicJSFragment: Sendable { ) static let jsObjectLiftRetainedObjectId = IntrinsicJSFragment( parameters: ["objectId"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) let resultLabel = scope.variable("value") let objectId = arguments[0] printer.write( @@ -287,13 +316,13 @@ struct IntrinsicJSFragment: Sendable { ) static let jsObjectLiftParameter = IntrinsicJSFragment( parameters: ["objectId"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, _ in return ["\(JSGlueVariableScope.reservedSwift).memory.getObject(\(arguments[0]))"] } ) static let jsObjectLowerReturn = IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, _ in return ["\(JSGlueVariableScope.reservedSwift).memory.retain(\(arguments[0]))"] } ) @@ -419,7 +448,8 @@ struct IntrinsicJSFragment: Sendable { static let jsValueLower = IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) let value = arguments[0] let kindVar = scope.variable("\(value)Kind") let payload1Var = scope.variable("\(value)Payload1") @@ -507,8 +537,9 @@ struct IntrinsicJSFragment: Sendable { // via the parameter stacks that `_swift_js_pop_*` read from. return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in - let lowered = try jsValueLower.printCode(arguments, scope, printer, cleanupCode) + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let lowered = try jsValueLower.printCode(arguments, context) let kindVar = lowered[0] let payload1Var = lowered[1] let payload2Var = lowered[2] @@ -523,8 +554,12 @@ struct IntrinsicJSFragment: Sendable { // to tmpRet stacks directly. return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in - let lowered = try jsValueLower.printCode(arguments, scope, printer, cleanupCode) + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let lowered = try jsValueLower.printCode( + arguments, + context + ) let kindVar = lowered[0] let payload1Var = lowered[1] let payload2Var = lowered[2] @@ -539,7 +574,8 @@ struct IntrinsicJSFragment: Sendable { static let jsValueLift = IntrinsicJSFragment( parameters: [], - printCode: { _, scope, printer, cleanupCode in + printCode: { _, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) let payload2 = scope.variable("jsValuePayload2") let payload1 = scope.variable("jsValuePayload1") let kind = scope.variable("jsValueKind") @@ -556,7 +592,8 @@ struct IntrinsicJSFragment: Sendable { ) static let jsValueLiftParameter = IntrinsicJSFragment( parameters: ["kind", "payload1", "payload2"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) let resultVar = scope.variable("jsValue") registerJSValueHelpers(scope: scope) printer.write( @@ -568,14 +605,14 @@ struct IntrinsicJSFragment: Sendable { static let swiftHeapObjectLowerParameter = IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in return ["\(arguments[0]).pointer"] } ) static func swiftHeapObjectLiftReturn(_ name: String) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in return ["\(name).__construct(\(arguments[0]))"] } ) @@ -583,14 +620,14 @@ struct IntrinsicJSFragment: Sendable { static func swiftHeapObjectLiftParameter(_ name: String) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["pointer"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in return ["_exports['\(name)'].__construct(\(arguments[0]))"] } ) } static let swiftHeapObjectLowerReturn = IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in return ["\(arguments[0]).pointer"] } ) @@ -598,7 +635,8 @@ struct IntrinsicJSFragment: Sendable { static func associatedEnumLowerParameter(enumBase: String) -> IntrinsicJSFragment { IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (printer, cleanup) = (context.printer, context.cleanupCode) let value = arguments[0] let caseIdName = "\(value)CaseId" let cleanupName = "\(value)Cleanup" @@ -614,7 +652,8 @@ struct IntrinsicJSFragment: Sendable { static func associatedEnumLiftReturn(enumBase: String) -> IntrinsicJSFragment { IntrinsicJSFragment( parameters: [], - printCode: { _, scope, printer, _ in + printCode: { _, context in + let (scope, printer) = (context.scope, context.printer) let retName = scope.variable("ret") printer.write( "const \(retName) = \(JSGlueVariableScope.reservedEnumHelpers).\(enumBase).lift(\(scope.popTag()));" @@ -628,13 +667,11 @@ struct IntrinsicJSFragment: Sendable { if case .jsValue = wrappedType { return IntrinsicJSFragment( parameters: ["isSome", "kind", "payload1", "payload2"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in let isSome = arguments[0] let lifted = try jsValueLiftParameter.printCode( [arguments[1], arguments[2], arguments[3]], - scope, - printer, - cleanupCode + context ) let valueExpr = lifted.first ?? "undefined" return ["\(isSome) ? \(valueExpr) : null"] @@ -644,7 +681,8 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["isSome", "wrappedValue"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let isSome = arguments[0] let wrappedValue = arguments[1] let resultExpr: String @@ -728,7 +766,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("if (\(isSome)) {") try printer.indent { let arrayLiftFragment = try arrayLift(elementType: elementType) - let liftResults = try arrayLiftFragment.printCode([], scope, printer, cleanupCode) + let liftResults = try arrayLiftFragment.printCode([], context) if let liftResult = liftResults.first { printer.write("\(arrayVar) = \(liftResult);") } @@ -745,7 +783,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("if (\(isSome)) {") try printer.indent { let dictLiftFragment = try dictionaryLift(valueType: valueType) - let liftResults = try dictLiftFragment.printCode([], scope, printer, cleanupCode) + let liftResults = try dictLiftFragment.printCode([], context) if let liftResult = liftResults.first { printer.write("\(dictVar) = \(liftResult);") } @@ -768,7 +806,8 @@ struct IntrinsicJSFragment: Sendable { static func optionalLowerParameter(wrappedType: BridgeType) throws -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) let value = arguments[0] let isSomeVar = scope.variable("isSome") printer.write("const \(isSomeVar) = \(value) != null;") @@ -808,7 +847,7 @@ struct IntrinsicJSFragment: Sendable { return ["+\(isSomeVar)", "\(isSomeVar) ? \(idVar) : 0", "\(isSomeVar) ? \(bytesVar).length : 0"] case .jsValue: - let lowered = try jsValueLower.printCode([value], scope, printer, cleanupCode) + let lowered = try jsValueLower.printCode([value], context) return ["+\(isSomeVar)"] + lowered case .associatedValueEnum(let fullName): let base = fullName.components(separatedBy: ".").last ?? fullName @@ -839,7 +878,10 @@ struct IntrinsicJSFragment: Sendable { try printer.indent { let arrayLowerFragment = try arrayLower(elementType: elementType) let arrayCleanup = CodeFragmentPrinter() - let _ = try arrayLowerFragment.printCode([value], scope, printer, arrayCleanup) + let _ = try arrayLowerFragment.printCode( + [value], + context.with(\.cleanupCode, arrayCleanup) + ) if !arrayCleanup.lines.isEmpty { for line in arrayCleanup.lines { printer.write("\(cleanupArrayVar).push(() => { \(line) });") @@ -856,7 +898,10 @@ struct IntrinsicJSFragment: Sendable { try printer.indent { let dictLowerFragment = try dictionaryLower(valueType: valueType) let dictCleanup = CodeFragmentPrinter() - let _ = try dictLowerFragment.printCode([value], scope, printer, dictCleanup) + let _ = try dictLowerFragment.printCode( + [value], + context.with(\.cleanupCode, dictCleanup) + ) if !dictCleanup.lines.isEmpty { for line in dictCleanup.lines { printer.write("\(cleanupArrayVar).push(() => { \(line) });") @@ -903,9 +948,11 @@ struct IntrinsicJSFragment: Sendable { kind: JSOptionalKind ) -> IntrinsicJSFragment { let absenceLiteral = kind.absenceLiteral + let bridgeContext = context return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let resultVar = scope.variable("optResult") switch wrappedType { case .bool: @@ -933,7 +980,7 @@ struct IntrinsicJSFragment: Sendable { ) printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject) = undefined;") let constructExpr = - context == .exportSwift + bridgeContext == .exportSwift ? "\(className).__construct(\(pointerVar))" : "_exports['\(className)'].__construct(\(pointerVar))" printer.write( @@ -1007,7 +1054,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("if (\(isSomeVar)) {") try printer.indent { let arrayLiftFragment = try arrayLift(elementType: elementType) - let liftResults = try arrayLiftFragment.printCode([], scope, printer, cleanupCode) + let liftResults = try arrayLiftFragment.printCode([], context) if let liftResult = liftResults.first { printer.write("\(resultVar) = \(liftResult);") } @@ -1024,7 +1071,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("if (\(isSomeVar)) {") try printer.indent { let dictLiftFragment = try dictionaryLift(valueType: valueType) - let liftResults = try dictLiftFragment.printCode([], scope, printer, cleanupCode) + let liftResults = try dictLiftFragment.printCode([], context) if let liftResult = liftResults.first { printer.write("\(resultVar) = \(liftResult);") } @@ -1040,7 +1087,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("let \(resultVar);") printer.write("if (\(isSomeVar)) {") try printer.indent { - let lifted = try jsValueLift.printCode([], scope, printer, cleanupCode) + let lifted = try jsValueLift.printCode([], context) if let liftedValue = lifted.first { printer.write("\(resultVar) = \(liftedValue);") } @@ -1068,7 +1115,8 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) let value = arguments[0] let isSomeVar = scope.variable("isSome") let presenceExpr = kind.presenceCheck(value: value) @@ -1114,7 +1162,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("bjs[\"swift_js_return_optional_object\"](\(isSomeVar) ? 1 : 0, \(idVar));") case .jsValue: if value != "undefined" { - let lowered = try jsValueLower.printCode([value], scope, printer, cleanupCode) + let lowered = try jsValueLower.printCode([value], context) let kindVar = lowered[0] let payload1Var = lowered[1] let payload2Var = lowered[2] @@ -1130,7 +1178,10 @@ struct IntrinsicJSFragment: Sendable { try printer.indent { let arrayLowerFragment = try arrayLower(elementType: elementType) let arrayCleanup = CodeFragmentPrinter() - let _ = try arrayLowerFragment.printCode([value], scope, printer, arrayCleanup) + let _ = try arrayLowerFragment.printCode( + [value], + context.with(\.cleanupCode, arrayCleanup) + ) if !arrayCleanup.lines.isEmpty { for line in arrayCleanup.lines { printer.write(line) @@ -1204,7 +1255,10 @@ struct IntrinsicJSFragment: Sendable { let keyFragment = try stackLowerFragment(elementType: .string) let keyCleanup = CodeFragmentPrinter() - let _ = try keyFragment.printCode([keyVar], scope, printer, keyCleanup) + let _ = try keyFragment.printCode( + [keyVar], + context.with(\.cleanupCode, keyCleanup) + ) if !keyCleanup.lines.isEmpty { printer.write("\(cleanupArrayVar).push(() => {") printer.indent { @@ -1217,7 +1271,10 @@ struct IntrinsicJSFragment: Sendable { let valueFragment = try stackLowerFragment(elementType: valueType) let valueCleanup = CodeFragmentPrinter() - let _ = try valueFragment.printCode([valueVar], scope, printer, valueCleanup) + let _ = try valueFragment.printCode( + [valueVar], + context.with(\.cleanupCode, valueCleanup) + ) if !valueCleanup.lines.isEmpty { printer.write("\(cleanupArrayVar).push(() => {") printer.indent { @@ -1268,7 +1325,8 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer let value = arguments[0] switch wrappedType { @@ -1299,7 +1357,8 @@ struct IntrinsicJSFragment: Sendable { case .int, .float, .double, .caseEnum: return IntrinsicJSFragment( parameters: ["value", "targetVar"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer printer.write("let \(arguments[1]) = \(arguments[0]);") return [] } @@ -1307,9 +1366,10 @@ struct IntrinsicJSFragment: Sendable { case .bool: return IntrinsicJSFragment( parameters: ["value", "targetVar"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer let baseFragment = boolLiftParameter - let lifted = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lifted = try baseFragment.printCode([arguments[0]], context) printer.write("let \(arguments[1]) = \(lifted[0]);") return [] } @@ -1317,9 +1377,10 @@ struct IntrinsicJSFragment: Sendable { case .string: return IntrinsicJSFragment( parameters: ["objectId", "targetVar"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer let baseFragment = stringLiftParameter - let lifted = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lifted = try baseFragment.printCode([arguments[0]], context) printer.write("let \(arguments[1]) = String(\(lifted[0]));") return [] } @@ -1329,9 +1390,10 @@ struct IntrinsicJSFragment: Sendable { case .string: return IntrinsicJSFragment( parameters: ["objectId", "targetVar"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer let baseFragment = stringLiftParameter - let lifted = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lifted = try baseFragment.printCode([arguments[0]], context) printer.write("let \(arguments[1]) = String(\(lifted[0]));") return [] } @@ -1339,9 +1401,10 @@ struct IntrinsicJSFragment: Sendable { case .bool: return IntrinsicJSFragment( parameters: ["value", "targetVar"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer let baseFragment = boolLiftParameter - let lifted = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lifted = try baseFragment.printCode([arguments[0]], context) printer.write("let \(arguments[1]) = \(lifted[0]);") return [] } @@ -1349,7 +1412,8 @@ struct IntrinsicJSFragment: Sendable { default: return IntrinsicJSFragment( parameters: ["value", "targetVar"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer printer.write("let \(arguments[1]) = \(arguments[0]);") return [] } @@ -1358,7 +1422,8 @@ struct IntrinsicJSFragment: Sendable { case .jsObject: return IntrinsicJSFragment( parameters: ["objectId", "targetVar"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer let objectId = arguments[0] let targetVar = arguments[1] printer.write( @@ -1371,7 +1436,8 @@ struct IntrinsicJSFragment: Sendable { case .swiftHeapObject(let name): return IntrinsicJSFragment( parameters: ["pointer", "targetVar"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer let pointer = arguments[0] let targetVar = arguments[1] printer.write("let \(targetVar) = _exports['\(name)'].__construct(\(pointer));") @@ -1381,7 +1447,8 @@ struct IntrinsicJSFragment: Sendable { case .associatedValueEnum(let fullName): return IntrinsicJSFragment( parameters: ["caseId", "targetVar"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer let caseId = arguments[0] let targetVar = arguments[1] let base = fullName.components(separatedBy: ".").last ?? fullName @@ -1416,7 +1483,8 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["isSome", "value", "targetVar"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let isSome = arguments[0] let value = arguments[1] let targetVar = arguments[2] @@ -1483,72 +1551,72 @@ struct IntrinsicJSFragment: Sendable { case .void: return IntrinsicJSFragment( parameters: ["result"], - printCode: { _, _, printer, _ in - printer.write("return;") + printCode: { _, context in + context.printer.write("return;") return [] } ) case .int, .caseEnum: return IntrinsicJSFragment( parameters: ["result"], - printCode: { arguments, scope, printer, cleanupCode in - printer.write("return \(arguments[0]) | 0;") + printCode: { arguments, context in + context.printer.write("return \(arguments[0]) | 0;") return [] } ) case .bool: return IntrinsicJSFragment( parameters: ["result"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in let baseFragment = boolLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) - printer.write("return \(lowered[0]);") + let lowered = try baseFragment.printCode([arguments[0]], context) + context.printer.write("return \(lowered[0]);") return [] } ) case .float: return IntrinsicJSFragment( parameters: ["result"], - printCode: { arguments, scope, printer, cleanupCode in - printer.write("return Math.fround(\(arguments[0]));") + printCode: { arguments, context in + context.printer.write("return Math.fround(\(arguments[0]));") return [] } ) case .double: return IntrinsicJSFragment( parameters: ["result"], - printCode: { arguments, scope, printer, cleanupCode in - printer.write("return \(arguments[0]);") + printCode: { arguments, context in + context.printer.write("return \(arguments[0]);") return [] } ) case .string: return IntrinsicJSFragment( parameters: ["result"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in let baseFragment = stringLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) - printer.write("return \(lowered[0]);") + let lowered = try baseFragment.printCode([arguments[0]], context) + context.printer.write("return \(lowered[0]);") return [] } ) case .jsObject: return IntrinsicJSFragment( parameters: ["result"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in let baseFragment = jsObjectLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) - printer.write("return \(lowered[0]);") + let lowered = try baseFragment.printCode([arguments[0]], context) + context.printer.write("return \(lowered[0]);") return [] } ) case .swiftHeapObject: return IntrinsicJSFragment( parameters: ["result"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in let baseFragment = swiftHeapObjectLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) - printer.write("return \(lowered[0]);") + let lowered = try baseFragment.printCode([arguments[0]], context) + context.printer.write("return \(lowered[0]);") return [] } ) @@ -1557,28 +1625,28 @@ struct IntrinsicJSFragment: Sendable { case .string: return IntrinsicJSFragment( parameters: ["result"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in let baseFragment = stringLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) - printer.write("return \(lowered[0]);") + let lowered = try baseFragment.printCode([arguments[0]], context) + context.printer.write("return \(lowered[0]);") return [] } ) case .bool: return IntrinsicJSFragment( parameters: ["result"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in let baseFragment = boolLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) - printer.write("return \(lowered[0]);") + let lowered = try baseFragment.printCode([arguments[0]], context) + context.printer.write("return \(lowered[0]);") return [] } ) default: return IntrinsicJSFragment( parameters: ["result"], - printCode: { arguments, scope, printer, cleanupCode in - printer.write("return \(arguments[0]) | 0;") + printCode: { arguments, context in + context.printer.write("return \(arguments[0]) | 0;") return [] } ) @@ -1586,7 +1654,8 @@ struct IntrinsicJSFragment: Sendable { case .associatedValueEnum(let fullName): return IntrinsicJSFragment( parameters: ["result"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) let result = arguments[0] let base = fullName.components(separatedBy: ".").last ?? fullName let caseIdVar = scope.variable("caseId") @@ -1610,7 +1679,8 @@ struct IntrinsicJSFragment: Sendable { private static func closureOptionalLowerReturn(wrappedType: BridgeType) throws -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["result"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) let result = arguments[0] switch wrappedType { @@ -1685,7 +1755,8 @@ struct IntrinsicJSFragment: Sendable { case .void: return IntrinsicJSFragment( parameters: ["invokeCall"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer printer.write("\(arguments[0]);") printer.write("return;") return [] @@ -1694,55 +1765,56 @@ struct IntrinsicJSFragment: Sendable { case .int, .caseEnum: return IntrinsicJSFragment( parameters: ["invokeCall"], - printCode: { arguments, scope, printer, cleanupCode in - printer.write("return \(arguments[0]) | 0;") + printCode: { arguments, context in + context.printer.write("return \(arguments[0]) | 0;") return [] } ) case .bool: return IntrinsicJSFragment( parameters: ["invokeCall"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in let baseFragment = boolLiftReturn - let lifted = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) - printer.write("return \(lifted[0]);") + let lifted = try baseFragment.printCode([arguments[0]], context) + context.printer.write("return \(lifted[0]);") return [] } ) case .float, .double: return IntrinsicJSFragment( parameters: ["invokeCall"], - printCode: { arguments, scope, printer, cleanupCode in - printer.write("return \(arguments[0]);") + printCode: { arguments, context in + context.printer.write("return \(arguments[0]);") return [] } ) case .string: return IntrinsicJSFragment( parameters: ["invokeCall"], - printCode: { arguments, scope, printer, cleanupCode in - printer.write("const resultLen = \(arguments[0]);") + printCode: { arguments, context in + context.printer.write("const resultLen = \(arguments[0]);") let baseFragment = stringLiftReturn - let lifted = try baseFragment.printCode([], scope, printer, cleanupCode) - printer.write("return \(lifted[0]);") + let lifted = try baseFragment.printCode([], context) + context.printer.write("return \(lifted[0]);") return [] } ) case .jsObject: return IntrinsicJSFragment( parameters: ["invokeCall"], - printCode: { arguments, scope, printer, cleanupCode in - printer.write("const resultId = \(arguments[0]);") + printCode: { arguments, context in + context.printer.write("const resultId = \(arguments[0]);") let baseFragment = jsObjectLiftReturn - let lifted = try baseFragment.printCode(["resultId"], scope, printer, cleanupCode) - printer.write("return \(lifted[0]);") + let lifted = try baseFragment.printCode(["resultId"], context) + context.printer.write("return \(lifted[0]);") return [] } ) case .swiftHeapObject(let className): return IntrinsicJSFragment( parameters: ["invokeCall"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer printer.write("const resultPtr = \(arguments[0]);") printer.write("return _exports['\(className)'].__construct(resultPtr);") return [] @@ -1751,7 +1823,8 @@ struct IntrinsicJSFragment: Sendable { case .closure: return IntrinsicJSFragment( parameters: ["invokeCall"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let funcRefVar = scope.variable("swiftClosureFuncRef") printer.write("const \(funcRefVar) = \(arguments[0]);") printer.write( @@ -1767,20 +1840,22 @@ struct IntrinsicJSFragment: Sendable { case .string: return IntrinsicJSFragment( parameters: ["invokeCall"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer printer.write("const resultLen = \(arguments[0]);") let baseFragment = stringLiftReturn - let lifted = try baseFragment.printCode([], scope, printer, cleanupCode) - printer.write("return \(lifted[0]);") + let lifted = try baseFragment.printCode([], context) + context.printer.write("return \(lifted[0]);") return [] } ) case .bool: return IntrinsicJSFragment( parameters: ["invokeCall"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer let baseFragment = boolLiftReturn - let lifted = try baseFragment.printCode([arguments[0]], scope, printer, cleanupCode) + let lifted = try baseFragment.printCode([arguments[0]], context) printer.write("return \(lifted[0]);") return [] } @@ -1788,8 +1863,8 @@ struct IntrinsicJSFragment: Sendable { default: return IntrinsicJSFragment( parameters: ["invokeCall"], - printCode: { arguments, scope, printer, cleanupCode in - printer.write("return \(arguments[0]) | 0;") + printCode: { arguments, context in + context.printer.write("return \(arguments[0]) | 0;") return [] } ) @@ -1797,7 +1872,8 @@ struct IntrinsicJSFragment: Sendable { case .associatedValueEnum(let fullName): return IntrinsicJSFragment( parameters: ["invokeCall"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) printer.write("\(arguments[0]);") let base = fullName.components(separatedBy: ".").last ?? fullName let resultVar = scope.variable("result") @@ -1822,7 +1898,8 @@ struct IntrinsicJSFragment: Sendable { ) throws -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["invokeCall"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer let invokeCall = arguments[0] printer.write("\(invokeCall);") let baseFragment = optionalLiftReturn( @@ -1830,7 +1907,7 @@ struct IntrinsicJSFragment: Sendable { context: .importTS, kind: kind ) - let lifted = try baseFragment.printCode([], scope, printer, cleanupCode) + let lifted = try baseFragment.printCode([], context) if !lifted.isEmpty { printer.write("return \(lifted[0]);") } @@ -1843,7 +1920,8 @@ struct IntrinsicJSFragment: Sendable { static func closureErrorReturn(type: BridgeType) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer switch type { case .void: printer.write("return;") @@ -1914,7 +1992,8 @@ struct IntrinsicJSFragment: Sendable { case .closure: return IntrinsicJSFragment( parameters: ["closure"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let closure = arguments[0] let callbackIdVar = scope.variable("callbackId") printer.write( @@ -1963,7 +2042,7 @@ struct IntrinsicJSFragment: Sendable { case .closure: return IntrinsicJSFragment( parameters: ["funcRef"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in let funcRef = arguments[0] return ["\(JSGlueVariableScope.reservedSwift).memory.getObject(\(funcRef))"] } @@ -2018,7 +2097,8 @@ struct IntrinsicJSFragment: Sendable { let base = fullName.components(separatedBy: ".").last ?? fullName return IntrinsicJSFragment( parameters: ["caseId"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let caseId = arguments[0] let resultVar = scope.variable("enumValue") printer.write( @@ -2036,7 +2116,8 @@ struct IntrinsicJSFragment: Sendable { let base = fullName.components(separatedBy: ".").last ?? fullName return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let resultVar = scope.variable("structValue") printer.write( "const \(resultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(base).lift();" @@ -2048,7 +2129,7 @@ struct IntrinsicJSFragment: Sendable { case .closure: return IntrinsicJSFragment( parameters: ["funcRef"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in let funcRef = arguments[0] return ["\(JSGlueVariableScope.reservedSwift).memory.getObject(\(funcRef))"] } @@ -2108,7 +2189,8 @@ struct IntrinsicJSFragment: Sendable { case .closure: return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let printer = context.printer let value = arguments[0] printer.write("if (typeof \(value) !== \"function\") {") printer.indent { @@ -2135,7 +2217,8 @@ struct IntrinsicJSFragment: Sendable { let base = fullName.components(separatedBy: ".").last ?? fullName return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) let value = arguments[0] let caseIdVar = scope.variable("caseId") let cleanupVar = scope.variable("cleanup") @@ -2154,7 +2237,8 @@ struct IntrinsicJSFragment: Sendable { static func associatedValueEnumValues(enumDefinition: ExportedEnum) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["enumName"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let printer = context.printer let enumName = arguments[0] printer.write("const \(enumName) = {") @@ -2181,7 +2265,8 @@ struct IntrinsicJSFragment: Sendable { static func associatedValueEnumHelperFactory(enumDefinition: ExportedEnum) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["enumName"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let enumName = arguments[0] printer.write("const __bjs_create\(enumName)Helpers = () => {") @@ -2206,9 +2291,11 @@ struct IntrinsicJSFragment: Sendable { let fragment = IntrinsicJSFragment.associatedValuePushPayload(enumCase: enumCase) _ = try fragment.printCode( ["value", enumName, caseName], - caseScope, - lowerPrinter, - caseCleanup + IntrinsicJSFragment.PrintCodeContext( + scope: caseScope, + printer: lowerPrinter, + cleanupCode: caseCleanup + ) ) } @@ -2237,7 +2324,14 @@ struct IntrinsicJSFragment: Sendable { let caseCleanup = CodeFragmentPrinter() let fragment = IntrinsicJSFragment.associatedValuePopPayload(enumCase: enumCase) - _ = try fragment.printCode([enumName, caseName], caseScope, liftPrinter, caseCleanup) + _ = try fragment.printCode( + [enumName, caseName], + IntrinsicJSFragment.PrintCodeContext( + scope: caseScope, + printer: liftPrinter, + cleanupCode: caseCleanup + ) + ) } for line in liftPrinter.lines { @@ -2264,7 +2358,8 @@ struct IntrinsicJSFragment: Sendable { static func simpleEnumHelper(enumDefinition: ExportedEnum) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["enumName"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let printer = context.printer let enumName = arguments[0] printer.write("const \(enumName) = {") printer.indent { @@ -2288,7 +2383,8 @@ struct IntrinsicJSFragment: Sendable { static func rawValueEnumHelper(enumDefinition: ExportedEnum) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["enumName"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let printer = context.printer let enumName = arguments[0] printer.write("const \(enumName) = {") printer.indent { @@ -2312,7 +2408,8 @@ struct IntrinsicJSFragment: Sendable { private static func associatedValuePushPayload(enumCase: EnumCase) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["value", "enumName", "caseName"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) let enumName = arguments[1] let caseName = arguments[2] @@ -2332,7 +2429,7 @@ struct IntrinsicJSFragment: Sendable { type: associatedValue.type ) - _ = try fragment.printCode(["value.\(prop)"], scope, printer, cleanup) + _ = try fragment.printCode(["value.\(prop)"], context) } if cleanup.lines.isEmpty { @@ -2356,7 +2453,8 @@ struct IntrinsicJSFragment: Sendable { private static func associatedValuePopPayload(enumCase: EnumCase) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["enumName", "caseName"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) let enumName = arguments[0] let caseName = arguments[1] @@ -2371,7 +2469,7 @@ struct IntrinsicJSFragment: Sendable { let prop = associatedValue.label ?? "param\(associatedValueIndex)" let fragment = try IntrinsicJSFragment.associatedValuePopPayload(type: associatedValue.type) - let result = try fragment.printCode([], scope, casePrinter, cleanup) + let result = try fragment.printCode([], context.with(\.printer, casePrinter)) let varName = result.first ?? "value_\(associatedValueIndex)" fieldPairs.append("\(prop): \(varName)") @@ -2409,7 +2507,8 @@ struct IntrinsicJSFragment: Sendable { ) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) let value = arguments[0] let isSomeVar = scope.variable("isSome") printer.write("const \(isSomeVar) = \(kind.presenceCheck(value: value));") @@ -2568,7 +2667,10 @@ struct IntrinsicJSFragment: Sendable { try printer.indent { let localCleanup = CodeFragmentPrinter() let arrFragment = try arrayLower(elementType: elementType) - _ = try arrFragment.printCode([value], scope, printer, localCleanup) + _ = try arrFragment.printCode( + [value], + context.with(\.cleanupCode, localCleanup) + ) let cleanupLines = localCleanup.lines.filter { !$0.trimmingCharacters(in: .whitespaces).isEmpty } @@ -2609,7 +2711,8 @@ struct IntrinsicJSFragment: Sendable { ) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) let optVar = scope.variable("optional") let isSomeVar = scope.variable("isSome") @@ -2628,7 +2731,7 @@ struct IntrinsicJSFragment: Sendable { ) } else { let wrappedFragment = try associatedValuePopPayload(type: wrappedType) - let wrappedResults = try wrappedFragment.printCode([], scope, printer, cleanup) + let wrappedResults = try wrappedFragment.printCode([], context) if let wrappedResult = wrappedResults.first { printer.write("\(optVar) = \(wrappedResult);") } else { @@ -2651,7 +2754,8 @@ struct IntrinsicJSFragment: Sendable { let base = fullName.components(separatedBy: ".").last ?? fullName return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) let value = arguments[0] let cleanupVar = scope.variable("cleanup") printer.write( @@ -2666,7 +2770,8 @@ struct IntrinsicJSFragment: Sendable { static func swiftStructLowerParameter(structBase: String) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) let value = arguments[0] let cleanupVar = scope.variable("cleanup") printer.write( @@ -2681,7 +2786,8 @@ struct IntrinsicJSFragment: Sendable { static func swiftStructLiftReturn(structBase: String) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let resultVar = scope.variable("structValue") printer.write( "const \(resultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(structBase).lift();" @@ -2697,7 +2803,8 @@ struct IntrinsicJSFragment: Sendable { static func arrayLower(elementType: BridgeType) throws -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["arr"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) let arr = arguments[0] let cleanupArrayVar = scope.variable("arrayCleanups") @@ -2707,7 +2814,10 @@ struct IntrinsicJSFragment: Sendable { try printer.indent { let elementFragment = try stackLowerFragment(elementType: elementType) let elementCleanup = CodeFragmentPrinter() - let _ = try elementFragment.printCode([elemVar], scope, printer, elementCleanup) + let _ = try elementFragment.printCode( + [elemVar], + context.with(\.cleanupCode, elementCleanup) + ) if !elementCleanup.lines.isEmpty { printer.write("\(cleanupArrayVar).push(() => {") printer.indent { @@ -2730,7 +2840,8 @@ struct IntrinsicJSFragment: Sendable { static func dictionaryLower(valueType: BridgeType) throws -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["dict"], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) let dict = arguments[0] let cleanupArrayVar = scope.variable("arrayCleanups") @@ -2746,7 +2857,10 @@ struct IntrinsicJSFragment: Sendable { let keyFragment = try stackLowerFragment(elementType: .string) let keyCleanup = CodeFragmentPrinter() - let _ = try keyFragment.printCode([keyVar], scope, printer, keyCleanup) + let _ = try keyFragment.printCode( + [keyVar], + context.with(\.cleanupCode, keyCleanup) + ) if !keyCleanup.lines.isEmpty { printer.write("\(cleanupArrayVar).push(() => {") printer.indent { @@ -2759,7 +2873,10 @@ struct IntrinsicJSFragment: Sendable { let valueFragment = try stackLowerFragment(elementType: valueType) let valueCleanup = CodeFragmentPrinter() - let _ = try valueFragment.printCode([valueVar], scope, printer, valueCleanup) + let _ = try valueFragment.printCode( + [valueVar], + context.with(\.cleanupCode, valueCleanup) + ) if !valueCleanup.lines.isEmpty { printer.write("\(cleanupArrayVar).push(() => {") printer.indent { @@ -2782,7 +2899,8 @@ struct IntrinsicJSFragment: Sendable { static func arrayLift(elementType: BridgeType) throws -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let resultVar = scope.variable("arrayResult") let lenVar = scope.variable("arrayLen") let iVar = scope.variable("i") @@ -2792,7 +2910,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("for (let \(iVar) = 0; \(iVar) < \(lenVar); \(iVar)++) {") try printer.indent { let elementFragment = try stackLiftFragment(elementType: elementType) - let elementResults = try elementFragment.printCode([], scope, printer, cleanupCode) + let elementResults = try elementFragment.printCode([], context) if let elementExpr = elementResults.first { printer.write("\(resultVar).push(\(elementExpr));") } @@ -2808,7 +2926,8 @@ struct IntrinsicJSFragment: Sendable { static func dictionaryLift(valueType: BridgeType) throws -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanupCode in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let resultVar = scope.variable("dictResult") let lenVar = scope.variable("dictLen") let iVar = scope.variable("i") @@ -2818,9 +2937,9 @@ struct IntrinsicJSFragment: Sendable { printer.write("for (let \(iVar) = 0; \(iVar) < \(lenVar); \(iVar)++) {") try printer.indent { let valueFragment = try stackLiftFragment(elementType: valueType) - let valueResults = try valueFragment.printCode([], scope, printer, cleanupCode) + let valueResults = try valueFragment.printCode([], context) let keyFragment = try stackLiftFragment(elementType: .string) - let keyResults = try keyFragment.printCode([], scope, printer, cleanupCode) + let keyResults = try keyFragment.printCode([], context) if let keyExpr = keyResults.first, let valueExpr = valueResults.first { printer.write("\(resultVar)[\(keyExpr)] = \(valueExpr);") } @@ -2836,7 +2955,8 @@ struct IntrinsicJSFragment: Sendable { case .jsValue: return IntrinsicJSFragment( parameters: [], - printCode: { _, scope, printer, cleanup in + printCode: { _, context in + let (scope, printer) = (context.scope, context.printer) let payload2Var = scope.variable("jsValuePayload2") let payload1Var = scope.variable("jsValuePayload1") let kindVar = scope.variable("jsValueKind") @@ -2854,7 +2974,8 @@ struct IntrinsicJSFragment: Sendable { case .string: return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let strVar = scope.variable("string") printer.write("const \(strVar) = \(scope.popString());") return [strVar] @@ -2863,7 +2984,8 @@ struct IntrinsicJSFragment: Sendable { case .bool: return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let bVar = scope.variable("bool") printer.write("const \(bVar) = \(scope.popI32()) !== 0;") return [bVar] @@ -2872,7 +2994,8 @@ struct IntrinsicJSFragment: Sendable { case .int, .uint: return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let iVar = scope.variable("int") printer.write("const \(iVar) = \(scope.popI32());") return [iVar] @@ -2881,7 +3004,8 @@ struct IntrinsicJSFragment: Sendable { case .float: return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let fVar = scope.variable("f32") printer.write("const \(fVar) = \(scope.popF32());") return [fVar] @@ -2890,7 +3014,8 @@ struct IntrinsicJSFragment: Sendable { case .double: return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let dVar = scope.variable("f64") printer.write("const \(dVar) = \(scope.popF64());") return [dVar] @@ -2900,7 +3025,8 @@ struct IntrinsicJSFragment: Sendable { let structBase = fullName.components(separatedBy: ".").last ?? fullName return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let resultVar = scope.variable("struct") printer.write( "const \(resultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(structBase).lift();" @@ -2911,7 +3037,8 @@ struct IntrinsicJSFragment: Sendable { case .caseEnum: return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let varName = scope.variable("caseId") printer.write("const \(varName) = \(scope.popI32());") return [varName] @@ -2922,7 +3049,8 @@ struct IntrinsicJSFragment: Sendable { case .string: return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let varName = scope.variable("rawValue") printer.write("const \(varName) = \(scope.popString());") return [varName] @@ -2931,7 +3059,8 @@ struct IntrinsicJSFragment: Sendable { case .float: return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let varName = scope.variable("rawValue") printer.write("const \(varName) = \(scope.popF32());") return [varName] @@ -2940,7 +3069,8 @@ struct IntrinsicJSFragment: Sendable { case .double: return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let varName = scope.variable("rawValue") printer.write("const \(varName) = \(scope.popF64());") return [varName] @@ -2949,7 +3079,8 @@ struct IntrinsicJSFragment: Sendable { default: return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let varName = scope.variable("rawValue") printer.write("const \(varName) = \(scope.popI32());") return [varName] @@ -2960,7 +3091,8 @@ struct IntrinsicJSFragment: Sendable { let base = fullName.components(separatedBy: ".").last ?? fullName return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let resultVar = scope.variable("enumValue") printer.write( "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(scope.popTag()), );" @@ -2971,7 +3103,8 @@ struct IntrinsicJSFragment: Sendable { case .swiftHeapObject(let className): return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let ptrVar = scope.variable("ptr") let objVar = scope.variable("obj") printer.write("const \(ptrVar) = \(scope.popPointer());") @@ -2982,7 +3115,8 @@ struct IntrinsicJSFragment: Sendable { case .jsObject, .swiftProtocol: return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let idVar = scope.variable("objId") let objVar = scope.variable("obj") printer.write("const \(idVar) = \(scope.popI32());") @@ -3000,7 +3134,8 @@ struct IntrinsicJSFragment: Sendable { case .unsafePointer: return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let pVar = scope.variable("pointer") printer.write("const \(pVar) = \(scope.popPointer());") return [pVar] @@ -3016,9 +3151,10 @@ struct IntrinsicJSFragment: Sendable { case .jsValue: return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) registerJSValueHelpers(scope: scope) - let lowered = try jsValueLower.printCode([arguments[0]], scope, printer, cleanup) + let lowered = try jsValueLower.printCode([arguments[0]], context) let kindVar = lowered[0] let payload1Var = lowered[1] let payload2Var = lowered[2] @@ -3031,7 +3167,8 @@ struct IntrinsicJSFragment: Sendable { case .string: return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) let value = arguments[0] let bytesVar = scope.variable("bytes") let idVar = scope.variable("id") @@ -3046,7 +3183,8 @@ struct IntrinsicJSFragment: Sendable { case .bool: return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) scope.emitPushI32Parameter("\(arguments[0]) ? 1 : 0", printer: printer) return [] } @@ -3054,7 +3192,8 @@ struct IntrinsicJSFragment: Sendable { case .int, .uint: return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) scope.emitPushI32Parameter("(\(arguments[0]) | 0)", printer: printer) return [] } @@ -3062,7 +3201,8 @@ struct IntrinsicJSFragment: Sendable { case .float: return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) scope.emitPushF32Parameter("Math.fround(\(arguments[0]))", printer: printer) return [] } @@ -3070,7 +3210,8 @@ struct IntrinsicJSFragment: Sendable { case .double: return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) scope.emitPushF64Parameter("\(arguments[0])", printer: printer) return [] } @@ -3079,7 +3220,8 @@ struct IntrinsicJSFragment: Sendable { let structBase = fullName.components(separatedBy: ".").last ?? fullName return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) let value = arguments[0] let cleanupVar = scope.variable("structCleanup") printer.write( @@ -3092,7 +3234,8 @@ struct IntrinsicJSFragment: Sendable { case .caseEnum: return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) scope.emitPushI32Parameter("(\(arguments[0]) | 0)", printer: printer) return [] } @@ -3102,7 +3245,8 @@ struct IntrinsicJSFragment: Sendable { case .string: return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) let value = arguments[0] let bytesVar = scope.variable("bytes") let idVar = scope.variable("id") @@ -3121,7 +3265,8 @@ struct IntrinsicJSFragment: Sendable { case .float: return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) scope.emitPushF32Parameter("Math.fround(\(arguments[0]))", printer: printer) return [] } @@ -3129,7 +3274,8 @@ struct IntrinsicJSFragment: Sendable { case .double: return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) scope.emitPushF64Parameter("\(arguments[0])", printer: printer) return [] } @@ -3137,7 +3283,8 @@ struct IntrinsicJSFragment: Sendable { default: return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) scope.emitPushI32Parameter("(\(arguments[0]) | 0)", printer: printer) return [] } @@ -3147,7 +3294,8 @@ struct IntrinsicJSFragment: Sendable { let base = fullName.components(separatedBy: ".").last ?? fullName return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) let value = arguments[0] let caseIdVar = scope.variable("caseId") let cleanupVar = scope.variable("enumCleanup") @@ -3162,7 +3310,8 @@ struct IntrinsicJSFragment: Sendable { case .swiftHeapObject: return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) scope.emitPushPointerParameter("\(arguments[0]).pointer", printer: printer) return [] } @@ -3170,7 +3319,8 @@ struct IntrinsicJSFragment: Sendable { case .jsObject: return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let value = arguments[0] let idVar = scope.variable("objId") printer.write("const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") @@ -3191,7 +3341,8 @@ struct IntrinsicJSFragment: Sendable { // Same as jsObject but no cleanup — Swift's AnyProtocol wrapper releases via deinit return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let value = arguments[0] let idVar = scope.variable("objId") printer.write("const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") @@ -3202,7 +3353,8 @@ struct IntrinsicJSFragment: Sendable { case .unsafePointer: return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) scope.emitPushPointerParameter("(\(arguments[0]) | 0)", printer: printer) return [] } @@ -3219,7 +3371,8 @@ struct IntrinsicJSFragment: Sendable { let absenceLiteral = kind.absenceLiteral return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) let isSomeVar = scope.variable("isSome") let resultVar = scope.variable("optValue") @@ -3232,7 +3385,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("} else {") try printer.indent { let innerFragment = try stackLiftFragment(elementType: wrappedType) - let innerResults = try innerFragment.printCode([], scope, printer, cleanup) + let innerResults = try innerFragment.printCode([], context) if let innerResult = innerResults.first { printer.write("\(resultVar) = \(innerResult);") } else { @@ -3252,7 +3405,8 @@ struct IntrinsicJSFragment: Sendable { ) throws -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let value = arguments[0] let isSomeVar = scope.variable("isSome") @@ -3263,7 +3417,10 @@ struct IntrinsicJSFragment: Sendable { printer.write("if (\(isSomeVar)) {") try printer.indent { let innerFragment = try stackLowerFragment(elementType: wrappedType) - let _ = try innerFragment.printCode([value], scope, printer, localCleanupWriter) + let _ = try innerFragment.printCode( + [value], + context.with(\.cleanupCode, localCleanupWriter) + ) let localCleanupLines = localCleanupWriter.lines.filter { !$0.trimmingCharacters(in: .whitespaces).isEmpty } @@ -3303,7 +3460,8 @@ struct IntrinsicJSFragment: Sendable { static func structHelper(structDefinition: ExportedStruct, allStructs: [ExportedStruct]) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["structName"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let printer = context.printer let structName = arguments[0] let capturedStructDef = structDefinition let capturedAllStructs = allStructs @@ -3320,8 +3478,7 @@ struct IntrinsicJSFragment: Sendable { try generateStructLowerCode( structDef: capturedStructDef, allStructs: capturedAllStructs, - scope: scope, - printer: printer + context: context ) } printer.write("},") @@ -3333,8 +3490,7 @@ struct IntrinsicJSFragment: Sendable { try generateStructLiftCode( structDef: capturedStructDef, allStructs: capturedAllStructs, - scope: scope, - printer: printer, + context: context, attachMethods: true ) } @@ -3356,9 +3512,9 @@ struct IntrinsicJSFragment: Sendable { private static func generateStructLowerCode( structDef: ExportedStruct, allStructs: [ExportedStruct], - scope: JSGlueVariableScope, - printer: CodeFragmentPrinter + context: IntrinsicJSFragment.PrintCodeContext ) throws { + let (scope, printer) = (context.scope, context.printer) let lowerPrinter = CodeFragmentPrinter() let lowerScope = scope.makeChildScope() let lowerCleanup = CodeFragmentPrinter() @@ -3368,7 +3524,14 @@ struct IntrinsicJSFragment: Sendable { for property in instanceProps { let fragment = try structFieldLowerFragment(field: property, allStructs: allStructs) let fieldValue = "value.\(property.name)" - _ = try fragment.printCode([fieldValue], lowerScope, lowerPrinter, lowerCleanup) + _ = try fragment.printCode( + [fieldValue], + IntrinsicJSFragment.PrintCodeContext( + scope: lowerScope, + printer: lowerPrinter, + cleanupCode: lowerCleanup, + ) + ) } for line in lowerPrinter.lines { @@ -3388,19 +3551,18 @@ struct IntrinsicJSFragment: Sendable { private static func generateStructLiftCode( structDef: ExportedStruct, allStructs: [ExportedStruct], - scope: JSGlueVariableScope, - printer: CodeFragmentPrinter, + context: IntrinsicJSFragment.PrintCodeContext, attachMethods: Bool = false ) throws { - let liftScope = scope.makeChildScope() - let liftCleanup = CodeFragmentPrinter() + let (scope, printer) = (context.scope, context.printer) + let liftScope = context.scope.makeChildScope() var fieldExpressions: [(name: String, expression: String)] = [] let instanceProps = structDef.properties.filter { !$0.isStatic } for property in instanceProps.reversed() { let fragment = try structFieldLiftFragment(field: property, allStructs: allStructs) - let results = try fragment.printCode([], liftScope, printer, liftCleanup) + let results = try fragment.printCode([], context) if let resultExpr = results.first { fieldExpressions.append((property.name, resultExpr)) @@ -3437,7 +3599,7 @@ struct IntrinsicJSFragment: Sendable { var paramForwardings: [String] = [] for param in method.parameters { let fragment = try IntrinsicJSFragment.lowerParameter(type: param.type) - let loweredValues = try fragment.printCode([param.name], methodScope, printer, methodCleanup) + let loweredValues = try fragment.printCode([param.name], context) paramForwardings.append(contentsOf: loweredValues) } @@ -3456,7 +3618,7 @@ struct IntrinsicJSFragment: Sendable { if method.returnType != .void { let liftFragment = try IntrinsicJSFragment.liftReturn(type: method.returnType) let liftArgs = liftFragment.parameters.isEmpty ? [] : ["ret"] - let lifted = try liftFragment.printCode(liftArgs, methodScope, printer, methodCleanup) + let lifted = try liftFragment.printCode(liftArgs, context) if let liftedValue = lifted.first { printer.write("return \(liftedValue);") } @@ -3481,7 +3643,8 @@ struct IntrinsicJSFragment: Sendable { case .jsObject: return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) let value = arguments[0] let idVar = scope.variable("id") printer.write("let \(idVar);") @@ -3511,7 +3674,8 @@ struct IntrinsicJSFragment: Sendable { case .nullable(let wrappedType, let kind): return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) let value = arguments[0] let isSomeVar = scope.variable("isSome") printer.write("const \(isSomeVar) = \(kind.presenceCheck(value: value));") @@ -3749,7 +3913,10 @@ struct IntrinsicJSFragment: Sendable { ) let guardedPrinter = CodeFragmentPrinter() let guardedCleanup = CodeFragmentPrinter() - _ = try wrappedFragment.printCode([value], scope, guardedPrinter, guardedCleanup) + _ = try wrappedFragment.printCode( + [value], + context.with(\.printer, guardedPrinter).with(\.cleanupCode, guardedCleanup) + ) var loweredLines = guardedPrinter.lines var hoistedCleanupVar: String? if let first = loweredLines.first { @@ -3788,13 +3955,14 @@ struct IntrinsicJSFragment: Sendable { case .swiftStruct(let nestedName): return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let value = arguments[0] let structResultVar = scope.variable("structResult") printer.write( "const \(structResultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(nestedName).lower(\(value));" ) - cleanup.write("if (\(structResultVar).cleanup) { \(structResultVar).cleanup(); }") + context.cleanupCode.write("if (\(structResultVar).cleanup) { \(structResultVar).cleanup(); }") return [] } ) @@ -3802,8 +3970,10 @@ struct IntrinsicJSFragment: Sendable { // These types should not appear as struct fields - return error fragment return IntrinsicJSFragment( parameters: ["value"], - printCode: { arguments, scope, printer, cleanup in - printer.write("throw new Error(\"Unsupported struct field type for lowering: \(field.type)\");") + printCode: { arguments, context in + context.printer.write( + "throw new Error(\"Unsupported struct field type for lowering: \(field.type)\");" + ) return [] } ) @@ -3867,7 +4037,8 @@ struct IntrinsicJSFragment: Sendable { case .nullable(let wrappedType, let kind): return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let isSomeVar = scope.variable("isSome") let optVar = scope.variable("optional") printer.write("const \(isSomeVar) = \(scope.popI32());") @@ -3892,7 +4063,7 @@ struct IntrinsicJSFragment: Sendable { ), allStructs: allStructs ) - let wrappedResults = try wrappedFragment.printCode([], scope, printer, cleanup) + let wrappedResults = try wrappedFragment.printCode([], context) if let wrappedResult = wrappedResults.first { printer.write("\(optVar) = \(wrappedResult);") } else { @@ -3911,7 +4082,8 @@ struct IntrinsicJSFragment: Sendable { case .swiftStruct(let nestedName): return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let structVar = scope.variable("struct") printer.write( "const \(structVar) = \(JSGlueVariableScope.reservedStructHelpers).\(nestedName).lift();" @@ -3922,7 +4094,8 @@ struct IntrinsicJSFragment: Sendable { case .jsObject: return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) let objectIdVar = scope.variable("objectId") let varName = scope.variable("value") printer.write("const \(objectIdVar) = \(scope.popI32());") @@ -3946,8 +4119,8 @@ struct IntrinsicJSFragment: Sendable { // These types should not appear as struct fields return IntrinsicJSFragment( parameters: [], - printCode: { arguments, scope, printer, cleanup in - printer.write("throw new Error(\"Unsupported struct field type: \(field.type)\");") + printCode: { arguments, context in + context.printer.write("throw new Error(\"Unsupported struct field type: \(field.type)\");") return [] } ) From 00d196786e464adf83ff0140bef1e7625e6d0348 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 9 Feb 2026 21:33:10 +0900 Subject: [PATCH 15/40] BridgeJS: Fix unused variable warnings in JSGlueGen.swift --- Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index c60cc2dbf..915ca2ea5 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -2409,7 +2409,7 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["value", "enumName", "caseName"], printCode: { arguments, context in - let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) + let (printer, cleanup) = (context.printer, context.cleanupCode) let enumName = arguments[1] let caseName = arguments[2] @@ -2454,7 +2454,7 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["enumName", "caseName"], printCode: { arguments, context in - let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) + let printer = context.printer let enumName = arguments[0] let caseName = arguments[1] @@ -2712,7 +2712,7 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: [], printCode: { arguments, context in - let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) + let (scope, printer) = (context.scope, context.printer) let optVar = scope.variable("optional") let isSomeVar = scope.variable("isSome") @@ -3152,7 +3152,7 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in - let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) + let (scope, printer) = (context.scope, context.printer) registerJSValueHelpers(scope: scope) let lowered = try jsValueLower.printCode([arguments[0]], context) let kindVar = lowered[0] @@ -3372,7 +3372,7 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: [], printCode: { arguments, context in - let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) + let (scope, printer) = (context.scope, context.printer) let isSomeVar = scope.variable("isSome") let resultVar = scope.variable("optValue") From f6959e04e88304826a6c4033b6122a81113dc5dd Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 9 Feb 2026 21:52:42 +0900 Subject: [PATCH 16/40] BridgeJS: Reduce `PrintCodeContext` construction usage --- .../Sources/BridgeJSLink/JSGlueGen.swift | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 915ca2ea5..4ec7f3f55 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -2291,11 +2291,7 @@ struct IntrinsicJSFragment: Sendable { let fragment = IntrinsicJSFragment.associatedValuePushPayload(enumCase: enumCase) _ = try fragment.printCode( ["value", enumName, caseName], - IntrinsicJSFragment.PrintCodeContext( - scope: caseScope, - printer: lowerPrinter, - cleanupCode: caseCleanup - ) + context.with(\.scope, caseScope).with(\.printer, lowerPrinter).with(\.cleanupCode, caseCleanup) ) } @@ -2326,11 +2322,7 @@ struct IntrinsicJSFragment: Sendable { let fragment = IntrinsicJSFragment.associatedValuePopPayload(enumCase: enumCase) _ = try fragment.printCode( [enumName, caseName], - IntrinsicJSFragment.PrintCodeContext( - scope: caseScope, - printer: liftPrinter, - cleanupCode: caseCleanup - ) + context.with(\.scope, caseScope).with(\.printer, liftPrinter).with(\.cleanupCode, caseCleanup) ) } @@ -3526,11 +3518,7 @@ struct IntrinsicJSFragment: Sendable { let fieldValue = "value.\(property.name)" _ = try fragment.printCode( [fieldValue], - IntrinsicJSFragment.PrintCodeContext( - scope: lowerScope, - printer: lowerPrinter, - cleanupCode: lowerCleanup, - ) + context.with(\.scope, lowerScope).with(\.printer, lowerPrinter).with(\.cleanupCode, lowerCleanup) ) } From cb45962b14993cc0963cf090c11e191c22fbdd86 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 9 Feb 2026 21:53:31 +0900 Subject: [PATCH 17/40] ./Utilities/format.swift --- Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 4ec7f3f55..510a361ff 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -2291,7 +2291,10 @@ struct IntrinsicJSFragment: Sendable { let fragment = IntrinsicJSFragment.associatedValuePushPayload(enumCase: enumCase) _ = try fragment.printCode( ["value", enumName, caseName], - context.with(\.scope, caseScope).with(\.printer, lowerPrinter).with(\.cleanupCode, caseCleanup) + context.with(\.scope, caseScope).with(\.printer, lowerPrinter).with( + \.cleanupCode, + caseCleanup + ) ) } @@ -2322,7 +2325,10 @@ struct IntrinsicJSFragment: Sendable { let fragment = IntrinsicJSFragment.associatedValuePopPayload(enumCase: enumCase) _ = try fragment.printCode( [enumName, caseName], - context.with(\.scope, caseScope).with(\.printer, liftPrinter).with(\.cleanupCode, caseCleanup) + context.with(\.scope, caseScope).with(\.printer, liftPrinter).with( + \.cleanupCode, + caseCleanup + ) ) } From f90d9183f24189fbe5c1bfa5afa87693a5d03f67 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sun, 8 Feb 2026 10:45:07 +0900 Subject: [PATCH 18/40] BridgeJS: Unify closure JS glue lift/lower --- .../Sources/BridgeJSLink/BridgeJSLink.swift | 122 +--- .../Sources/BridgeJSLink/JSGlueGen.swift | 624 +----------------- .../BridgeJSLinkTests/SwiftClosure.js | 506 ++++++-------- .../BridgeJSLinkTests/SwiftClosureImports.js | 18 +- 4 files changed, 251 insertions(+), 1019 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index 7e6ce9b55..2c800ef0b 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -716,71 +716,25 @@ public struct BridgeJSLink { signature: ClosureSignature, functionName: String ) throws -> [String] { - let printer = CodeFragmentPrinter() - let context = IntrinsicJSFragment.PrintCodeContext( - scope: JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry), - printer: printer, - cleanupCode: CodeFragmentPrinter() - ) + let thunkBuilder = ImportedThunkBuilder(context: .exportSwift, intrinsicRegistry: intrinsicRegistry) + thunkBuilder.parameterNames.append("callbackId") + thunkBuilder.body.write("const callback = \(JSGlueVariableScope.reservedSwift).memory.getObject(callbackId);") - // Build parameter list for invoke function - var invokeParams: [String] = ["callbackId"] for (index, paramType) in signature.parameters.enumerated() { - if case .nullable = paramType { - invokeParams.append("param\(index)IsSome") - invokeParams.append("param\(index)Value") - } else { - invokeParams.append("param\(index)Id") - } + let paramName = "param\(index)" + try thunkBuilder.liftParameter(param: Parameter(label: nil, name: paramName, type: paramType)) } - printer.nextLine() - printer.write("bjs[\"\(functionName)\"] = function(\(invokeParams.joined(separator: ", "))) {") - try printer.indent { - printer.write("try {") - try printer.indent { - printer.write("const callback = \(JSGlueVariableScope.reservedSwift).memory.getObject(callbackId);") + let returnExpr = try thunkBuilder.call(calleeExpr: "callback", returnType: signature.returnType) - for (index, paramType) in signature.parameters.enumerated() { - let fragment = try IntrinsicJSFragment.closureLiftParameter(type: paramType) - let args: [String] - if case .nullable = paramType { - args = ["param\(index)IsSome", "param\(index)Value", "param\(index)"] - } else { - args = ["param\(index)Id", "param\(index)"] - } - _ = try fragment.printCode(args, context) - } - - let callbackParams = signature.parameters.indices.map { "param\($0)" }.joined(separator: ", ") - printer.write("const result = callback(\(callbackParams));") - - // Type check if needed (for example, formatName requires string return) - switch signature.returnType { - case .string: - printer.write("if (typeof result !== \"string\") {") - printer.indent { - printer.write("throw new TypeError(\"Callback must return a string\");") - } - printer.write("}") - default: - break - } - - let returnFragment = try IntrinsicJSFragment.closureLowerReturn(type: signature.returnType) - _ = try returnFragment.printCode(["result"], context) - } - printer.write("} catch (error) {") - try printer.indent { - printer.write("\(JSGlueVariableScope.reservedSetException)?.(error);") - let errorFragment = IntrinsicJSFragment.closureErrorReturn(type: signature.returnType) - _ = try errorFragment.printCode([], context) - } - printer.write("}") - } - printer.write("};") + var functionLines = thunkBuilder.renderFunction( + name: nil, + returnExpr: returnExpr, + returnType: signature.returnType + ) + functionLines[0] = "bjs[\"\(functionName)\"] = " + functionLines[0] - return printer.lines + return functionLines } /// Generates a lower_closure_* function that wraps a Swift closure for JavaScript @@ -789,46 +743,27 @@ public struct BridgeJSLink { functionName: String ) throws -> [String] { let printer = CodeFragmentPrinter() - let context = IntrinsicJSFragment.PrintCodeContext( - scope: JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry), - printer: printer, - cleanupCode: CodeFragmentPrinter() + let builder = ExportedThunkBuilder( + effects: Effects(isAsync: false, isThrows: true), + hasDirectAccessToSwiftClass: false, + intrinsicRegistry: intrinsicRegistry ) + builder.parameterForwardings.append("boxPtr") printer.write( "const \(functionName) = function(\(signature.parameters.indices.map { "param\($0)" }.joined(separator: ", "))) {" ) try printer.indent { - var invokeArgs: [String] = ["boxPtr"] - + // Lower parameters using shared thunk builder for (index, paramType) in signature.parameters.enumerated() { let paramName = "param\(index)" - let fragment = try IntrinsicJSFragment.lowerParameter(type: paramType) - let lowered = try fragment.printCode([paramName], context) - invokeArgs.append(contentsOf: lowered) + try builder.lowerParameter(param: Parameter(label: nil, name: paramName, type: paramType)) } - // Call the Swift invoke function let invokeCall = - "\(JSGlueVariableScope.reservedInstance).exports.invoke_swift_closure_\(signature.moduleName)_\(signature.mangleName)(\(invokeArgs.joined(separator: ", ")))" - let invokeResultName = "invokeResult" - printer.write("const \(invokeResultName) = \(invokeCall);") - - printer.write("if (\(JSGlueVariableScope.reservedStorageToReturnException)) {") - printer.indent { - printer.write( - "const error = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(JSGlueVariableScope.reservedStorageToReturnException));" - ) - printer.write( - "\(JSGlueVariableScope.reservedSwift).memory.release(\(JSGlueVariableScope.reservedStorageToReturnException));" - ) - printer.write("\(JSGlueVariableScope.reservedStorageToReturnException) = undefined;") - printer.write("throw error;") - } - printer.write("}") - - let returnFragment = try IntrinsicJSFragment.closureLiftReturn(type: signature.returnType) - _ = try returnFragment.printCode([invokeResultName], context) + "invoke_swift_closure_\(signature.moduleName)_\(signature.mangleName)" + let returnExpr = try builder.call(abiName: invokeCall, returnType: signature.returnType) + builder.renderFunctionBody(into: printer, returnExpr: returnExpr) } printer.write("};") @@ -1291,7 +1226,7 @@ public struct BridgeJSLink { let scope: JSGlueVariableScope let context: IntrinsicJSFragment.PrintCodeContext - init(effects: Effects, intrinsicRegistry: JSIntrinsicRegistry) { + init(effects: Effects, hasDirectAccessToSwiftClass: Bool = true, intrinsicRegistry: JSIntrinsicRegistry) { self.effects = effects self.scope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) self.body = CodeFragmentPrinter() @@ -1299,7 +1234,8 @@ public struct BridgeJSLink { self.context = IntrinsicJSFragment.PrintCodeContext( scope: scope, printer: body, - cleanupCode: cleanupCode + cleanupCode: cleanupCode, + hasDirectAccessToSwiftClass: hasDirectAccessToSwiftClass ) } @@ -2221,13 +2157,13 @@ extension BridgeJSLink { } func renderFunction( - name: String, + name: String?, returnExpr: String?, returnType: BridgeType ) -> [String] { let printer = CodeFragmentPrinter() - printer.write("function \(name)(\(parameterNames.joined(separator: ", "))) {") + printer.write("function\(name.map { " \($0)" } ?? "")(\(parameterNames.joined(separator: ", "))) {") printer.indent { printer.write("try {") printer.indent { @@ -2259,7 +2195,7 @@ extension BridgeJSLink { return try call(name: name, fromObjectExpr: "imports", returnType: returnType) } - private func call(calleeExpr: String, returnType: BridgeType) throws -> String? { + func call(calleeExpr: String, returnType: BridgeType) throws -> String? { let callExpr = "\(calleeExpr)(\(parameterForwardings.joined(separator: ", ")))" return try self.call(callExpr: callExpr, returnType: returnType) } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 510a361ff..9f1eddfdd 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -154,6 +154,9 @@ struct IntrinsicJSFragment: Sendable { var printer: CodeFragmentPrinter /// The printer to print the code that is expected to be executed at the end of the caller of the fragment. var cleanupCode: CodeFragmentPrinter + /// Whether the fragment has direct access to the SwiftHeapObject classes. + /// If false, the fragment needs to use `_exports[""]` to access the class. + var hasDirectAccessToSwiftClass: Bool = true func with(_ keyPath: WritableKeyPath, _ value: T) -> PrintCodeContext { var new = self @@ -613,7 +616,9 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in - return ["\(name).__construct(\(arguments[0]))"] + return [ + "\(context.hasDirectAccessToSwiftClass ? name : "_exports['\(name)']").__construct(\(arguments[0]))" + ] } ) } @@ -944,11 +949,9 @@ struct IntrinsicJSFragment: Sendable { static func optionalLiftReturn( wrappedType: BridgeType, - context: BridgeContext = .exportSwift, kind: JSOptionalKind ) -> IntrinsicJSFragment { let absenceLiteral = kind.absenceLiteral - let bridgeContext = context return IntrinsicJSFragment( parameters: [], printCode: { arguments, context in @@ -980,7 +983,7 @@ struct IntrinsicJSFragment: Sendable { ) printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject) = undefined;") let constructExpr = - bridgeContext == .exportSwift + context.hasDirectAccessToSwiftClass ? "\(className).__construct(\(pointerVar))" : "_exports['\(className)'].__construct(\(pointerVar))" printer.write( @@ -1349,619 +1352,6 @@ struct IntrinsicJSFragment: Sendable { ) } - // MARK: - Closure Support - - /// Lifts a WASM parameter to JS for passing to a JS callback (invoke_js_callback_*) - static func closureLiftParameter(type: BridgeType) throws -> IntrinsicJSFragment { - switch type { - case .int, .float, .double, .caseEnum: - return IntrinsicJSFragment( - parameters: ["value", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - printer.write("let \(arguments[1]) = \(arguments[0]);") - return [] - } - ) - case .bool: - return IntrinsicJSFragment( - parameters: ["value", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - let baseFragment = boolLiftParameter - let lifted = try baseFragment.printCode([arguments[0]], context) - printer.write("let \(arguments[1]) = \(lifted[0]);") - return [] - } - ) - case .string: - return IntrinsicJSFragment( - parameters: ["objectId", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - let baseFragment = stringLiftParameter - let lifted = try baseFragment.printCode([arguments[0]], context) - printer.write("let \(arguments[1]) = String(\(lifted[0]));") - return [] - } - ) - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - return IntrinsicJSFragment( - parameters: ["objectId", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - let baseFragment = stringLiftParameter - let lifted = try baseFragment.printCode([arguments[0]], context) - printer.write("let \(arguments[1]) = String(\(lifted[0]));") - return [] - } - ) - case .bool: - return IntrinsicJSFragment( - parameters: ["value", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - let baseFragment = boolLiftParameter - let lifted = try baseFragment.printCode([arguments[0]], context) - printer.write("let \(arguments[1]) = \(lifted[0]);") - return [] - } - ) - default: - return IntrinsicJSFragment( - parameters: ["value", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - printer.write("let \(arguments[1]) = \(arguments[0]);") - return [] - } - ) - } - case .jsObject: - return IntrinsicJSFragment( - parameters: ["objectId", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - let objectId = arguments[0] - let targetVar = arguments[1] - printer.write( - "let \(targetVar) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(objectId));" - ) - printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(objectId));") - return [] - } - ) - case .swiftHeapObject(let name): - return IntrinsicJSFragment( - parameters: ["pointer", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - let pointer = arguments[0] - let targetVar = arguments[1] - printer.write("let \(targetVar) = _exports['\(name)'].__construct(\(pointer));") - return [] - } - ) - case .associatedValueEnum(let fullName): - return IntrinsicJSFragment( - parameters: ["caseId", "targetVar"], - printCode: { arguments, context in - let printer = context.printer - let caseId = arguments[0] - let targetVar = arguments[1] - let base = fullName.components(separatedBy: ".").last ?? fullName - printer.write( - "let \(targetVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(caseId));" - ) - return [] - } - ) - case .nullable(let wrappedType, let kind): - return try closureOptionalLiftParameter(wrappedType: wrappedType, kind: kind) - default: - throw BridgeJSLinkError(message: "Unsupported closure parameter type for lifting: \(type)") - } - } - - /// Handles optional parameter lifting for closure invocation. - private static func closureOptionalLiftParameter( - wrappedType: BridgeType, - kind: JSOptionalKind - ) throws -> IntrinsicJSFragment { - let absenceLiteral = kind.absenceLiteral - switch wrappedType { - case .string, .rawValueEnum, .int, .bool, .double, .float, .jsObject, .swiftHeapObject, .caseEnum, - .associatedValueEnum, .closure: - break - default: - throw BridgeJSLinkError( - message: "Unsupported optional wrapped type in closure parameter lifting: \(wrappedType)" - ) - } - - return IntrinsicJSFragment( - parameters: ["isSome", "value", "targetVar"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let isSome = arguments[0] - let value = arguments[1] - let targetVar = arguments[2] - - printer.write("let \(targetVar);") - printer.write("if (\(isSome)) {") - printer.indent() - switch wrappedType { - case .string, .rawValueEnum(_, .string): - let objectLabel = scope.variable("\(targetVar)Object") - printer.write( - "const \(objectLabel) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(value));" - ) - printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(value));") - printer.write("\(targetVar) = String(\(objectLabel));") - case .int, .uint: - printer.write("\(targetVar) = \(value) | 0;") - case .bool: - printer.write("\(targetVar) = \(value) !== 0;") - case .double: - printer.write("\(targetVar) = \(value);") - case .float: - printer.write("\(targetVar) = Math.fround(\(value));") - case .jsObject: - printer.write("\(targetVar) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(value));") - printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(value));") - case .swiftHeapObject(let typeName): - printer.write("\(targetVar) = _exports['\(typeName)'].__construct(\(value));") - case .caseEnum: - printer.write("\(targetVar) = \(value);") - case .rawValueEnum(_, let rawType): - switch rawType { - case .bool: - printer.write("\(targetVar) = \(value) !== 0;") - default: - printer.write("\(targetVar) = \(value);") - } - case .associatedValueEnum(let fullName): - let base = fullName.components(separatedBy: ".").last ?? fullName - printer.write( - "\(targetVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(value));" - ) - case .closure: - printer.write("\(targetVar) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(value));") - printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(value));") - default: - fatalError("Unsupported optional wrapped type in closure parameter lifting: \(wrappedType)") - } - printer.unindent() - printer.write("} else {") - printer.indent() - printer.write("\(targetVar) = \(absenceLiteral);") - printer.unindent() - printer.write("}") - - return [] - } - ) - } - - /// Lowers a JS return value to WASM for returning from callback (invoke_js_callback_*) - static func closureLowerReturn(type: BridgeType) throws -> IntrinsicJSFragment { - switch type { - case .void: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { _, context in - context.printer.write("return;") - return [] - } - ) - case .int, .caseEnum: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - context.printer.write("return \(arguments[0]) | 0;") - return [] - } - ) - case .bool: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - let baseFragment = boolLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], context) - context.printer.write("return \(lowered[0]);") - return [] - } - ) - case .float: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - context.printer.write("return Math.fround(\(arguments[0]));") - return [] - } - ) - case .double: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - context.printer.write("return \(arguments[0]);") - return [] - } - ) - case .string: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - let baseFragment = stringLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], context) - context.printer.write("return \(lowered[0]);") - return [] - } - ) - case .jsObject: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - let baseFragment = jsObjectLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], context) - context.printer.write("return \(lowered[0]);") - return [] - } - ) - case .swiftHeapObject: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - let baseFragment = swiftHeapObjectLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], context) - context.printer.write("return \(lowered[0]);") - return [] - } - ) - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - let baseFragment = stringLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], context) - context.printer.write("return \(lowered[0]);") - return [] - } - ) - case .bool: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - let baseFragment = boolLowerReturn - let lowered = try baseFragment.printCode([arguments[0]], context) - context.printer.write("return \(lowered[0]);") - return [] - } - ) - default: - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - context.printer.write("return \(arguments[0]) | 0;") - return [] - } - ) - } - case .associatedValueEnum(let fullName): - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) - let result = arguments[0] - let base = fullName.components(separatedBy: ".").last ?? fullName - let caseIdVar = scope.variable("caseId") - let cleanupVar = scope.variable("cleanup") - printer.write( - "const { caseId: \(caseIdVar), cleanup: \(cleanupVar) } = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(result));" - ) - cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") - printer.write("return \(caseIdVar);") - return [] - } - ) - case .nullable(let wrappedType, _): - return try closureOptionalLowerReturn(wrappedType: wrappedType) - default: - throw BridgeJSLinkError(message: "Unsupported closure return type for lowering: \(type)") - } - } - - /// Handles optional return lowering for closure invocation - private static func closureOptionalLowerReturn(wrappedType: BridgeType) throws -> IntrinsicJSFragment { - return IntrinsicJSFragment( - parameters: ["result"], - printCode: { arguments, context in - let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) - let result = arguments[0] - - switch wrappedType { - case .swiftHeapObject: - printer.write("return \(result) ? \(result).pointer : 0;") - case .string: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = \(result);") - printer.write("return;") - case .int, .uint: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = \(result);") - printer.write("return;") - case .bool: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalBool) = \(result);") - printer.write("return;") - case .float: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = \(result);") - printer.write("return;") - case .double: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = \(result);") - printer.write("return;") - case .caseEnum: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = \(result);") - printer.write("return;") - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = \(result);") - printer.write("return;") - case .bool: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalBool) = \(result);") - printer.write("return;") - case .float: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = \(result);") - printer.write("return;") - case .double: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = \(result);") - printer.write("return;") - default: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = \(result);") - printer.write("return;") - } - case .associatedValueEnum(let fullName): - let base = fullName.components(separatedBy: ".").last ?? fullName - let caseIdVar = scope.variable("caseId") - let cleanupVar = scope.variable("cleanup") - printer.write("if (\(result)) {") - printer.indent() - printer.write( - "const { caseId: \(caseIdVar), cleanup: \(cleanupVar) } = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(result));" - ) - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = \(caseIdVar);") - cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") - printer.unindent() - printer.write("} else {") - printer.indent() - printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = null;") - printer.unindent() - printer.write("}") - printer.write("return;") - default: - fatalError("Unsupported optional wrapped type in closure return lowering: \(wrappedType)") - } - - return [] - } - ) - } - - /// Lifts a WASM return value to JS from Swift closure (lower_closure_*) - static func closureLiftReturn(type: BridgeType) throws -> IntrinsicJSFragment { - switch type { - case .void: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - let printer = context.printer - printer.write("\(arguments[0]);") - printer.write("return;") - return [] - } - ) - case .int, .caseEnum: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - context.printer.write("return \(arguments[0]) | 0;") - return [] - } - ) - case .bool: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - let baseFragment = boolLiftReturn - let lifted = try baseFragment.printCode([arguments[0]], context) - context.printer.write("return \(lifted[0]);") - return [] - } - ) - case .float, .double: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - context.printer.write("return \(arguments[0]);") - return [] - } - ) - case .string: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - context.printer.write("const resultLen = \(arguments[0]);") - let baseFragment = stringLiftReturn - let lifted = try baseFragment.printCode([], context) - context.printer.write("return \(lifted[0]);") - return [] - } - ) - case .jsObject: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - context.printer.write("const resultId = \(arguments[0]);") - let baseFragment = jsObjectLiftReturn - let lifted = try baseFragment.printCode(["resultId"], context) - context.printer.write("return \(lifted[0]);") - return [] - } - ) - case .swiftHeapObject(let className): - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - let printer = context.printer - printer.write("const resultPtr = \(arguments[0]);") - printer.write("return _exports['\(className)'].__construct(resultPtr);") - return [] - } - ) - case .closure: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let funcRefVar = scope.variable("swiftClosureFuncRef") - printer.write("const \(funcRefVar) = \(arguments[0]);") - printer.write( - "const funcObj = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(funcRefVar));" - ) - printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(funcRefVar));") - printer.write("return funcObj;") - return [] - } - ) - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - let printer = context.printer - printer.write("const resultLen = \(arguments[0]);") - let baseFragment = stringLiftReturn - let lifted = try baseFragment.printCode([], context) - context.printer.write("return \(lifted[0]);") - return [] - } - ) - case .bool: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - let printer = context.printer - let baseFragment = boolLiftReturn - let lifted = try baseFragment.printCode([arguments[0]], context) - printer.write("return \(lifted[0]);") - return [] - } - ) - default: - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - context.printer.write("return \(arguments[0]) | 0;") - return [] - } - ) - } - case .associatedValueEnum(let fullName): - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - printer.write("\(arguments[0]);") - let base = fullName.components(separatedBy: ".").last ?? fullName - let resultVar = scope.variable("result") - printer.write( - "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(scope.popTag()));" - ) - printer.write("return \(resultVar);") - return [] - } - ) - case .nullable(let wrappedType, let kind): - return try closureOptionalLiftReturn(wrappedType: wrappedType, kind: kind) - default: - throw BridgeJSLinkError(message: "Unsupported closure return type for lifting: \(type)") - } - } - - /// Handles optional return lifting for Swift closure returns - private static func closureOptionalLiftReturn( - wrappedType: BridgeType, - kind: JSOptionalKind - ) throws -> IntrinsicJSFragment { - return IntrinsicJSFragment( - parameters: ["invokeCall"], - printCode: { arguments, context in - let printer = context.printer - let invokeCall = arguments[0] - printer.write("\(invokeCall);") - let baseFragment = optionalLiftReturn( - wrappedType: wrappedType, - context: .importTS, - kind: kind - ) - let lifted = try baseFragment.printCode([], context) - if !lifted.isEmpty { - printer.write("return \(lifted[0]);") - } - return [] - } - ) - } - - /// Provides appropriate default values for error cases in closure invocation - static func closureErrorReturn(type: BridgeType) -> IntrinsicJSFragment { - return IntrinsicJSFragment( - parameters: [], - printCode: { arguments, context in - let printer = context.printer - switch type { - case .void: - printer.write("return;") - case .string: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnBytes) = new Uint8Array(0);") - printer.write("return 0;") - case .int, .bool, .caseEnum: - printer.write("return 0;") - case .float, .double: - printer.write("return 0.0;") - case .jsObject, .swiftHeapObject: - printer.write("return 0;") - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - printer.write("\(JSGlueVariableScope.reservedStorageToReturnBytes) = new Uint8Array(0);") - printer.write("return 0;") - case .bool, .int, .int32, .int64, .uint, .uint32, .uint64: - printer.write("return 0;") - case .float, .double: - printer.write("return 0.0;") - } - case .associatedValueEnum: - printer.write("return;") - case .nullable(let wrappedType, _): - switch wrappedType { - case .swiftHeapObject: - printer.write("return 0;") - default: - printer.write("return;") - } - default: - printer.write("return 0;") - } - - return [] - } - ) - } - // MARK: - ExportSwift /// Returns a fragment that lowers a JS value to Wasm core values for parameters diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js index 09f9aee59..2ef9aaf5a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js @@ -328,337 +328,299 @@ export async function createInstantiator(options, swift) { const func = swift.memory.getObject(funcRef); func.__unregister(); } - - bjs["invoke_js_callback_TestModule_10TestModule10HttpStatusO_10HttpStatusO"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModule10HttpStatusO_10HttpStatusO"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = param0Id; - const result = callback(param0); - return result | 0; + let ret = callback(param0); + return ret; } catch (error) { - setException?.(error); - return 0; + setException(error); + return 0 } - }; + } bjs["make_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO(boxPtr, param0); + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - return invokeResult | 0; + return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO); } - - bjs["invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - const param0IdObject = swift.memory.getObject(param0Id); - swift.memory.release(param0Id); - let param0 = String(param0IdObject); - const result = callback(param0); - tmpRetBytes = textEncoder.encode(result); + const param0Object = swift.memory.getObject(param0); + swift.memory.release(param0); + let ret = callback(param0Object); + tmpRetBytes = textEncoder.encode(ret); return tmpRetBytes.length; } catch (error) { - setException?.(error); - tmpRetBytes = new Uint8Array(0); - return 0; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModule5ThemeO_5ThemeO = function(param0) { const param0Bytes = textEncoder.encode(param0); const param0Id = swift.memory.retain(param0Bytes); - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO(boxPtr, param0Id, param0Bytes.length); + instance.exports.invoke_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO(boxPtr, param0Id, param0Bytes.length); + const ret = tmpRetString; + tmpRetString = undefined; + swift.memory.release(param0Id); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - const resultLen = invokeResult; - const ret = tmpRetString; - tmpRetString = undefined; return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule5ThemeO_5ThemeO); } - - bjs["invoke_js_callback_TestModule_10TestModule6PersonC_6PersonC"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModule6PersonC_6PersonC"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = _exports['Person'].__construct(param0Id); - const result = callback(param0); - return result.pointer; + let ret = callback(_exports['Person'].__construct(param0)); + return ret.pointer; } catch (error) { - setException?.(error); - return 0; + setException(error); + return 0 } - }; + } bjs["make_swift_closure_TestModule_10TestModule6PersonC_6PersonC"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModule6PersonC_6PersonC = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule6PersonC_6PersonC(boxPtr, param0.pointer); + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModule6PersonC_6PersonC(boxPtr, param0.pointer); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - const resultPtr = invokeResult; - return _exports['Person'].__construct(resultPtr); + return _exports['Person'].__construct(ret); }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule6PersonC_6PersonC); } - - bjs["invoke_js_callback_TestModule_10TestModule9APIResultO_9APIResultO"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModule9APIResultO_9APIResultO"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = enumHelpers.APIResult.lift(param0Id); - const result = callback(param0); - const { caseId: caseId, cleanup: cleanup } = enumHelpers.APIResult.lower(result); + const enumValue = enumHelpers.APIResult.lift(param0); + let ret = callback(enumValue); + const { caseId: caseId, cleanup: cleanup } = enumHelpers.APIResult.lower(ret); return caseId; } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModule9APIResultO_9APIResultO = function(param0) { const { caseId: param0CaseId, cleanup: param0Cleanup } = enumHelpers.APIResult.lower(param0); - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO(boxPtr, param0CaseId); + instance.exports.invoke_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO(boxPtr, param0CaseId); + const ret = enumHelpers.APIResult.lift(tagStack.pop()); + if (param0Cleanup) { param0Cleanup(); } if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const result = enumHelpers.APIResult.lift(tagStack.pop()); - return result; + return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule9APIResultO_9APIResultO); } - - bjs["invoke_js_callback_TestModule_10TestModule9DirectionO_9DirectionO"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModule9DirectionO_9DirectionO"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = param0Id; - const result = callback(param0); - return result | 0; + let ret = callback(param0); + return ret; } catch (error) { - setException?.(error); - return 0; + setException(error); + return 0 } - }; + } bjs["make_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModule9DirectionO_9DirectionO = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO(boxPtr, param0); + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - return invokeResult | 0; + return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule9DirectionO_9DirectionO); } - - bjs["invoke_js_callback_TestModule_10TestModuleSS_SS"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModuleSS_SS"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - const param0IdObject = swift.memory.getObject(param0Id); - swift.memory.release(param0Id); - let param0 = String(param0IdObject); - const result = callback(param0); - if (typeof result !== "string") { - throw new TypeError("Callback must return a string"); - } - tmpRetBytes = textEncoder.encode(result); + const param0Object = swift.memory.getObject(param0); + swift.memory.release(param0); + let ret = callback(param0Object); + tmpRetBytes = textEncoder.encode(ret); return tmpRetBytes.length; } catch (error) { - setException?.(error); - tmpRetBytes = new Uint8Array(0); - return 0; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSS_SS"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSS_SS = function(param0) { const param0Bytes = textEncoder.encode(param0); const param0Id = swift.memory.retain(param0Bytes); - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSS_SS(boxPtr, param0Id, param0Bytes.length); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSS_SS(boxPtr, param0Id, param0Bytes.length); + const ret = tmpRetString; + tmpRetString = undefined; + swift.memory.release(param0Id); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - const resultLen = invokeResult; - const ret = tmpRetString; - tmpRetString = undefined; return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSS_SS); } - - bjs["invoke_js_callback_TestModule_10TestModuleSb_Sb"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModuleSb_Sb"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = param0Id !== 0; - const result = callback(param0); - return result ? 1 : 0; + let ret = callback(param0 !== 0); + return ret ? 1 : 0; } catch (error) { - setException?.(error); - return 0; + setException(error); + return 0 } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSb_Sb"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSb_Sb = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSb_Sb(boxPtr, param0); + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModuleSb_Sb(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - return invokeResult !== 0; + return ret !== 0; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSb_Sb); } - - bjs["invoke_js_callback_TestModule_10TestModuleSd_Sd"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModuleSd_Sd"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = param0Id; - const result = callback(param0); - return result; + let ret = callback(param0); + return ret; } catch (error) { - setException?.(error); - return 0.0; + setException(error); + return 0 } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSd_Sd"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSd_Sd = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSd_Sd(boxPtr, param0); + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModuleSd_Sd(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - return invokeResult; + return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSd_Sd); } - - bjs["invoke_js_callback_TestModule_10TestModuleSf_Sf"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModuleSf_Sf"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = param0Id; - const result = callback(param0); - return Math.fround(result); + let ret = callback(param0); + return ret; } catch (error) { - setException?.(error); - return 0.0; + setException(error); + return 0 } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSf_Sf"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSf_Sf = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSf_Sf(boxPtr, param0); + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModuleSf_Sf(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - return invokeResult; + return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSf_Sf); } - - bjs["invoke_js_callback_TestModule_10TestModuleSi_Si"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModuleSi_Si"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = param0Id; - const result = callback(param0); - return result | 0; + let ret = callback(param0); + return ret; } catch (error) { - setException?.(error); - return 0; + setException(error); + return 0 } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSi_Si"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSi_Si = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSi_Si(boxPtr, param0); + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModuleSi_Si(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - return invokeResult | 0; + return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSi_Si); } - - bjs["invoke_js_callback_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; - if (param0IsSome) { - param0 = param0Value; - } else { - param0 = null; - } - const result = callback(param0); - tmpRetOptionalInt = result; - return; + let ret = callback(param0IsSome ? param0WrappedValue : null); + const isSome = ret != null; + bjs["swift_js_return_optional_int"](isSome ? 1 : 0, isSome ? (ret | 0) : 0); } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO = function(param0) { const isSome = param0 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(boxPtr, +isSome, isSome ? param0 : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const optResult = tmpRetOptionalInt; - tmpRetOptionalInt = undefined; return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO); } - - bjs["invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; + let obj; if (param0IsSome) { - const param0Object = swift.memory.getObject(param0Value); - swift.memory.release(param0Value); - param0 = String(param0Object); + obj = swift.memory.getObject(param0WrappedValue); + swift.memory.release(param0WrappedValue); + } + let ret = callback(param0IsSome ? obj : null); + const isSome = ret != null; + if (isSome) { + tmpRetString = ret; } else { - param0 = null; + tmpRetString = null; } - const result = callback(param0); - tmpRetString = result; - return; } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO = function(param0) { const isSome = param0 != null; @@ -667,78 +629,68 @@ export async function createInstantiator(options, swift) { param0Bytes = textEncoder.encode(param0); param0Id = swift.memory.retain(param0Bytes); } - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(boxPtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(boxPtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + if (param0Id != undefined) { + swift.memory.release(param0Id); + } if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const optResult = tmpRetString; - tmpRetString = undefined; return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO); } - - bjs["invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; - if (param0IsSome) { - param0 = _exports['Person'].__construct(param0Value); - } else { - param0 = null; - } - const result = callback(param0); - return result ? result.pointer : 0; + let ret = callback(param0IsSome ? _exports['Person'].__construct(param0WrappedValue) : null); + const isSome = ret != null; + return isSome ? ret.pointer : 0; } catch (error) { - setException?.(error); - return 0; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC = function(param0) { const isSome = param0 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC(boxPtr, +isSome, isSome ? param0.pointer : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC(boxPtr, +isSome, isSome ? param0.pointer : 0); + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + const optResult = pointer === null ? null : _exports['Person'].__construct(pointer); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const pointer = tmpRetOptionalHeapObject; - tmpRetOptionalHeapObject = undefined; - const optResult = pointer === null ? null : _exports['Person'].__construct(pointer); return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC); } - - bjs["invoke_js_callback_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; + let enumValue; if (param0IsSome) { - param0 = enumHelpers.APIResult.lift(param0Value); - } else { - param0 = null; + enumValue = enumHelpers.APIResult.lift(param0WrappedValue); } - const result = callback(param0); - if (result) { - const { caseId: caseId, cleanup: cleanup } = enumHelpers.APIResult.lower(result); - tmpRetOptionalInt = caseId; + let ret = callback(param0IsSome ? enumValue : null); + const isSome = ret != null; + if (isSome) { + const { caseId: caseId, cleanup: cleanup } = enumHelpers.APIResult.lower(ret); + return caseId; } else { - tmpRetOptionalInt = null; + return -1; } - return; } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO = function(param0) { const isSome = param0 != null; @@ -748,14 +700,7 @@ export async function createInstantiator(options, swift) { param0CaseId = enumResult.caseId; param0Cleanup = enumResult.cleanup; } - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(boxPtr, +isSome, isSome ? param0CaseId : 0); - if (tmpRetException) { - const error = swift.memory.getObject(tmpRetException); - swift.memory.release(tmpRetException); - tmpRetException = undefined; - throw error; - } - invokeResult; + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(boxPtr, +isSome, isSome ? param0CaseId : 0); const tag = tagStack.pop(); const isNull = (tag === -1); let optResult; @@ -764,65 +709,62 @@ export async function createInstantiator(options, swift) { } else { optResult = enumHelpers.APIResult.lift(tag); } + if (param0Cleanup) { param0Cleanup(); } + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO); } - - bjs["invoke_js_callback_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; - if (param0IsSome) { - param0 = param0Value; - } else { - param0 = null; - } - const result = callback(param0); - tmpRetOptionalInt = result; - return; + let ret = callback(param0IsSome ? param0WrappedValue : null); + const isSome = ret != null; + return isSome ? (ret | 0) : -1; } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO = function(param0) { const isSome = param0 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(boxPtr, +isSome, isSome ? param0 : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const optResult = tmpRetOptionalInt; - tmpRetOptionalInt = undefined; return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO); } - - bjs["invoke_js_callback_TestModule_10TestModuleSqSS_SqSS"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSqSS_SqSS"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; + let obj; if (param0IsSome) { - const param0Object = swift.memory.getObject(param0Value); - swift.memory.release(param0Value); - param0 = String(param0Object); + obj = swift.memory.getObject(param0WrappedValue); + swift.memory.release(param0WrappedValue); + } + let ret = callback(param0IsSome ? obj : null); + const isSome = ret != null; + if (isSome) { + tmpRetString = ret; } else { - param0 = null; + tmpRetString = null; } - const result = callback(param0); - tmpRetString = result; - return; } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSqSS_SqSS"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSqSS_SqSS = function(param0) { const isSome = param0 != null; @@ -831,156 +773,122 @@ export async function createInstantiator(options, swift) { param0Bytes = textEncoder.encode(param0); param0Id = swift.memory.retain(param0Bytes); } - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSS_SqSS(boxPtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSS_SqSS(boxPtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + if (param0Id != undefined) { + swift.memory.release(param0Id); + } if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const optResult = tmpRetString; - tmpRetString = undefined; return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSS_SqSS); } - - bjs["invoke_js_callback_TestModule_10TestModuleSqSb_SqSb"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSqSb_SqSb"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; - if (param0IsSome) { - param0 = param0Value !== 0; - } else { - param0 = null; - } - const result = callback(param0); - tmpRetOptionalBool = result; - return; + let ret = callback(param0IsSome ? param0WrappedValue !== 0 : null); + const isSome = ret != null; + bjs["swift_js_return_optional_bool"](isSome ? 1 : 0, isSome ? (ret ? 1 : 0) : 0); } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSqSb_SqSb"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSqSb_SqSb = function(param0) { const isSome = param0 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSb_SqSb(boxPtr, +isSome, isSome ? param0 : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSb_SqSb(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalBool; + tmpRetOptionalBool = undefined; if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const optResult = tmpRetOptionalBool; - tmpRetOptionalBool = undefined; return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSb_SqSb); } - - bjs["invoke_js_callback_TestModule_10TestModuleSqSd_SqSd"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSqSd_SqSd"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; - if (param0IsSome) { - param0 = param0Value; - } else { - param0 = null; - } - const result = callback(param0); - tmpRetOptionalDouble = result; - return; + let ret = callback(param0IsSome ? param0WrappedValue : null); + const isSome = ret != null; + bjs["swift_js_return_optional_double"](isSome ? 1 : 0, isSome ? ret : 0.0); } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSqSd_SqSd"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSqSd_SqSd = function(param0) { const isSome = param0 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSd_SqSd(boxPtr, +isSome, isSome ? param0 : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSd_SqSd(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const optResult = tmpRetOptionalDouble; - tmpRetOptionalDouble = undefined; return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSd_SqSd); } - - bjs["invoke_js_callback_TestModule_10TestModuleSqSf_SqSf"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSqSf_SqSf"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; - if (param0IsSome) { - param0 = Math.fround(param0Value); - } else { - param0 = null; - } - const result = callback(param0); - tmpRetOptionalFloat = result; - return; + let ret = callback(param0IsSome ? param0WrappedValue : null); + const isSome = ret != null; + bjs["swift_js_return_optional_float"](isSome ? 1 : 0, isSome ? Math.fround(ret) : 0.0); } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSqSf_SqSf"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSqSf_SqSf = function(param0) { const isSome = param0 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSf_SqSf(boxPtr, +isSome, isSome ? param0 : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSf_SqSf(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const optResult = tmpRetOptionalFloat; - tmpRetOptionalFloat = undefined; return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSf_SqSf); } - - bjs["invoke_js_callback_TestModule_10TestModuleSqSi_SqSi"] = function(callbackId, param0IsSome, param0Value) { + bjs["invoke_js_callback_TestModule_10TestModuleSqSi_SqSi"] = function(callbackId, param0IsSome, param0WrappedValue) { try { const callback = swift.memory.getObject(callbackId); - let param0; - if (param0IsSome) { - param0 = param0Value | 0; - } else { - param0 = null; - } - const result = callback(param0); - tmpRetOptionalInt = result; - return; + let ret = callback(param0IsSome ? param0WrappedValue : null); + const isSome = ret != null; + bjs["swift_js_return_optional_int"](isSome ? 1 : 0, isSome ? (ret | 0) : 0); } catch (error) { - setException?.(error); - return; + setException(error); } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSqSi_SqSi"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSqSi_SqSi = function(param0) { const isSome = param0 != null; - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSi_SqSi(boxPtr, +isSome, isSome ? param0 : 0); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSi_SqSi(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - invokeResult; - const optResult = tmpRetOptionalInt; - tmpRetOptionalInt = undefined; return optResult; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSi_SqSi); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js index 57b34d426..98899d4df 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js @@ -228,28 +228,26 @@ export async function createInstantiator(options, swift) { const func = swift.memory.getObject(funcRef); func.__unregister(); } - - bjs["invoke_js_callback_TestModule_10TestModuleSi_Si"] = function(callbackId, param0Id) { + bjs["invoke_js_callback_TestModule_10TestModuleSi_Si"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); - let param0 = param0Id; - const result = callback(param0); - return result | 0; + let ret = callback(param0); + return ret; } catch (error) { - setException?.(error); - return 0; + setException(error); + return 0 } - }; + } bjs["make_swift_closure_TestModule_10TestModuleSi_Si"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSi_Si = function(param0) { - const invokeResult = instance.exports.invoke_swift_closure_TestModule_10TestModuleSi_Si(boxPtr, param0); + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModuleSi_Si(boxPtr, param0); if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); swift.memory.release(tmpRetException); tmpRetException = undefined; throw error; } - return invokeResult | 0; + return ret; }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSi_Si); } From bceaf282812d4d341ec21f22a525d6c7301c90f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Feb 2026 17:50:31 +0000 Subject: [PATCH 19/40] Bump actions/setup-node from 4 to 6 Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 6. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v4...v6) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7b5a808bc..68d6dac21 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -85,7 +85,7 @@ jobs: steps: - uses: actions/checkout@v6 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '20' - name: Install TypeScript From c6f2642275b2777da95c03c0e98845d48b12e5da Mon Sep 17 00:00:00 2001 From: Krzysztof Rodak Date: Mon, 9 Feb 2026 18:51:58 +0100 Subject: [PATCH 20/40] BridgeJS: Fix incorrect TypeScript type names for `tsEnum`-style enums and struct associated values --- .../Sources/BridgeJSLink/BridgeJSLink.swift | 13 +++++++++++-- .../BridgeJSLinkTests/EnumAssociatedValue.d.ts | 4 ++-- .../__Snapshots__/BridgeJSLinkTests/EnumCase.d.ts | 6 +++--- .../BridgeJSLinkTests/EnumRawType.d.ts | 12 ++++++------ 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index 13ea4e910..59ab9428b 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -1470,6 +1470,9 @@ public struct BridgeJSLink { case .namespaceEnum: return enumDef.tsFullPath default: + if enumDef.emitStyle == .tsEnum { + return enumDef.tsFullPath + } return "\(enumDef.tsFullPath)Tag" } } @@ -1786,7 +1789,7 @@ public struct BridgeJSLink { ] for (associatedValueIndex, associatedValue) in enumCase.associatedValues.enumerated() { let prop = associatedValue.label ?? "param\(associatedValueIndex)" - fields.append("\(prop): \(associatedValue.type.tsType)") + fields.append("\(prop): \(resolveTypeScriptType(associatedValue.type))") } unionParts.append("{ \(fields.joined(separator: "; ")) }") } @@ -2917,6 +2920,7 @@ extension BridgeJSLink { depth: 1, printer: printer, exposeToGlobal: true, + exportedSkeletons: exportedSkeletons, renderTSSignatureCallback: renderTSSignatureCallback ) printer.unindent() @@ -2935,6 +2939,7 @@ extension BridgeJSLink { depth: 1, printer: printer, exposeToGlobal: false, + exportedSkeletons: exportedSkeletons, renderTSSignatureCallback: renderTSSignatureCallback ) } @@ -2948,6 +2953,7 @@ extension BridgeJSLink { depth: Int, printer: CodeFragmentPrinter, exposeToGlobal: Bool, + exportedSkeletons: [ExportedSkeleton], renderTSSignatureCallback: @escaping ([Parameter], BridgeType, Effects) -> String ) { func hasContent(node: NamespaceNode) -> Bool { @@ -3102,7 +3108,9 @@ extension BridgeJSLink { .enumerated() { let prop = associatedValue.label ?? "param\(associatedValueIndex)" - fields.append("\(prop): \(associatedValue.type.tsType)") + fields.append( + "\(prop): \(BridgeJSLink.resolveTypeScriptType(associatedValue.type, exportedSkeletons: exportedSkeletons))" + ) } unionParts.append("{ \(fields.joined(separator: "; ")) }") } @@ -3136,6 +3144,7 @@ extension BridgeJSLink { depth: depth + 1, printer: printer, exposeToGlobal: exposeToGlobal, + exportedSkeletons: exportedSkeletons, renderTSSignatureCallback: renderTSSignatureCallback ) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.d.ts index 9ab117011..13f77ae08 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.d.ts @@ -82,7 +82,7 @@ export const AllTypesResultValues: { }; export type AllTypesResultTag = - { tag: typeof AllTypesResultValues.Tag.StructPayload; param0: PointTag } | { tag: typeof AllTypesResultValues.Tag.ClassPayload; param0: User } | { tag: typeof AllTypesResultValues.Tag.JsObjectPayload; param0: any } | { tag: typeof AllTypesResultValues.Tag.NestedEnum; param0: APIResultTag } | { tag: typeof AllTypesResultValues.Tag.ArrayPayload; param0: number[] } | { tag: typeof AllTypesResultValues.Tag.Empty } + { tag: typeof AllTypesResultValues.Tag.StructPayload; param0: Point } | { tag: typeof AllTypesResultValues.Tag.ClassPayload; param0: User } | { tag: typeof AllTypesResultValues.Tag.JsObjectPayload; param0: any } | { tag: typeof AllTypesResultValues.Tag.NestedEnum; param0: APIResultTag } | { tag: typeof AllTypesResultValues.Tag.ArrayPayload; param0: number[] } | { tag: typeof AllTypesResultValues.Tag.Empty } export const OptionalAllTypesResultValues: { readonly Tag: { @@ -96,7 +96,7 @@ export const OptionalAllTypesResultValues: { }; export type OptionalAllTypesResultTag = - { tag: typeof OptionalAllTypesResultValues.Tag.OptStruct; param0: PointTag | null } | { tag: typeof OptionalAllTypesResultValues.Tag.OptClass; param0: User | null } | { tag: typeof OptionalAllTypesResultValues.Tag.OptJSObject; param0: any | null } | { tag: typeof OptionalAllTypesResultValues.Tag.OptNestedEnum; param0: APIResultTag | null } | { tag: typeof OptionalAllTypesResultValues.Tag.OptArray; param0: number[] | null } | { tag: typeof OptionalAllTypesResultValues.Tag.Empty } + { tag: typeof OptionalAllTypesResultValues.Tag.OptStruct; param0: Point | null } | { tag: typeof OptionalAllTypesResultValues.Tag.OptClass; param0: User | null } | { tag: typeof OptionalAllTypesResultValues.Tag.OptJSObject; param0: any | null } | { tag: typeof OptionalAllTypesResultValues.Tag.OptNestedEnum; param0: APIResultTag | null } | { tag: typeof OptionalAllTypesResultValues.Tag.OptArray; param0: number[] | null } | { tag: typeof OptionalAllTypesResultValues.Tag.Empty } export interface Point { x: number; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.d.ts index 47fb52d94..5581df31e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.d.ts @@ -42,9 +42,9 @@ export type Exports = { getDirection(): DirectionTag; processDirection(input: DirectionTag): StatusTag; roundTripOptionalDirection(input: DirectionTag | null): DirectionTag | null; - setTSDirection(direction: TSDirectionTag): void; - getTSDirection(): TSDirectionTag; - roundTripOptionalTSDirection(input: TSDirectionTag | null): TSDirectionTag | null; + setTSDirection(direction: TSDirection): void; + getTSDirection(): TSDirection; + roundTripOptionalTSDirection(input: TSDirection | null): TSDirection | null; Direction: DirectionObject Status: StatusObject PublicStatus: PublicStatusObject diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.d.ts index 170d7f07d..50a45a58d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.d.ts @@ -113,18 +113,18 @@ export type Exports = { setTheme(theme: ThemeTag): void; getTheme(): ThemeTag; roundTripOptionalTheme(input: ThemeTag | null): ThemeTag | null; - setTSTheme(theme: TSThemeTag): void; - getTSTheme(): TSThemeTag; - roundTripOptionalTSTheme(input: TSThemeTag | null): TSThemeTag | null; + setTSTheme(theme: TSTheme): void; + getTSTheme(): TSTheme; + roundTripOptionalTSTheme(input: TSTheme | null): TSTheme | null; setFeatureFlag(flag: FeatureFlagTag): void; getFeatureFlag(): FeatureFlagTag; roundTripOptionalFeatureFlag(input: FeatureFlagTag | null): FeatureFlagTag | null; setHttpStatus(status: HttpStatusTag): void; getHttpStatus(): HttpStatusTag; roundTripOptionalHttpStatus(input: HttpStatusTag | null): HttpStatusTag | null; - setTSHttpStatus(status: TSHttpStatusTag): void; - getTSHttpStatus(): TSHttpStatusTag; - roundTripOptionalHttpStatus(input: TSHttpStatusTag | null): TSHttpStatusTag | null; + setTSHttpStatus(status: TSHttpStatus): void; + getTSHttpStatus(): TSHttpStatus; + roundTripOptionalHttpStatus(input: TSHttpStatus | null): TSHttpStatus | null; setPriority(priority: PriorityTag): void; getPriority(): PriorityTag; roundTripOptionalPriority(input: PriorityTag | null): PriorityTag | null; From 935130c27b45feb253dc6531d1b9f7ab7854087e Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Tue, 10 Feb 2026 11:12:54 +0900 Subject: [PATCH 21/40] BridgeJS: Update `JSUndefinedOr` APIs - Rename `optionalRepresentation` to `asOptional`. - Remove `undefinedValue` static property and use `.undefined` case directly. --- .../Sources/BridgeJSCore/ExportSwift.swift | 6 +- .../JavaScriptKit/BridgeJSIntrinsics.swift | 70 +++++++++---------- Sources/JavaScriptKit/JSUndefinedOr.swift | 19 +++-- .../DictionaryTests.swift | 2 +- .../OptionalSupportTests.swift | 2 +- 5 files changed, 55 insertions(+), 44 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index 70ed8f8a8..913bc076b 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -156,7 +156,7 @@ public class ExportSwift { let absentExpr = kind == .null ? "\(optionalSwiftType)<[\(swiftTypeName)]>.none" - : "\(optionalSwiftType)<[\(swiftTypeName)]>.undefinedValue" + : "\(optionalSwiftType)<[\(swiftTypeName)]>.undefined" liftingExpr = ExprSyntax( """ { @@ -934,7 +934,7 @@ struct StackCodegen { let swiftTypeName = elementType.swiftType let absentExpr = kind == .null - ? "\(typeName)<[\(swiftTypeName)]>.none" : "\(typeName)<[\(swiftTypeName)]>.undefinedValue" + ? "\(typeName)<[\(swiftTypeName)]>.none" : "\(typeName)<[\(swiftTypeName)]>.undefined" return """ { let __isSome = _swift_js_pop_i32() @@ -951,7 +951,7 @@ struct StackCodegen { let absentExpr = kind == .null ? "\(typeName)<[String: \(swiftTypeName)]>.none" - : "\(typeName)<[String: \(swiftTypeName)]>.undefinedValue" + : "\(typeName)<[String: \(swiftTypeName)]>.undefined" return """ { let __isSome = _swift_js_pop_i32() diff --git a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift index 4c8fdf3db..496b515c9 100644 --- a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift +++ b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift @@ -143,7 +143,7 @@ public protocol _BridgedSwiftStackType { /// Used by JSUndefinedOr so all bridge methods delegate to Optional. public protocol _BridgedAsOptional { associatedtype Wrapped - var optionalRepresentation: Wrapped? { get } + var asOptional: Wrapped? { get } init(optional: Wrapped?) } @@ -2019,7 +2019,7 @@ extension Optional where Wrapped: _BridgedSwiftStruct { extension _BridgedAsOptional where Wrapped == Bool { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { - optionalRepresentation.bridgeJSLowerParameter() + asOptional.bridgeJSLowerParameter() } @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Self { @@ -2035,13 +2035,13 @@ extension _BridgedAsOptional where Wrapped == Bool { } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } extension _BridgedAsOptional where Wrapped == Int { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { - optionalRepresentation.bridgeJSLowerParameter() + asOptional.bridgeJSLowerParameter() } @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Self { @@ -2057,13 +2057,13 @@ extension _BridgedAsOptional where Wrapped == Int { } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } extension _BridgedAsOptional where Wrapped == UInt { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { - optionalRepresentation.bridgeJSLowerParameter() + asOptional.bridgeJSLowerParameter() } @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Self { @@ -2079,13 +2079,13 @@ extension _BridgedAsOptional where Wrapped == UInt { } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } extension _BridgedAsOptional where Wrapped == String { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { - optionalRepresentation.bridgeJSLowerParameter() + asOptional.bridgeJSLowerParameter() } @_spi(BridgeJS) public static func bridgeJSLiftParameter( @@ -2105,13 +2105,13 @@ extension _BridgedAsOptional where Wrapped == String { } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } extension _BridgedAsOptional where Wrapped == JSObject { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { - optionalRepresentation.bridgeJSLowerParameter() + asOptional.bridgeJSLowerParameter() } @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ objectId: Int32) -> Self { @@ -2123,7 +2123,7 @@ extension _BridgedAsOptional where Wrapped == JSObject { } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } @@ -2133,20 +2133,20 @@ extension _BridgedAsOptional where Wrapped: _BridgedSwiftProtocolWrapper { } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } extension _BridgedAsOptional where Wrapped: _BridgedSwiftHeapObject { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, pointer: UnsafeMutableRawPointer) { - optionalRepresentation.bridgeJSLowerParameter() + asOptional.bridgeJSLowerParameter() } @_spi(BridgeJS) public consuming func bridgeJSLowerParameterWithRetain() -> ( isSome: Int32, pointer: UnsafeMutableRawPointer ) { - optionalRepresentation.bridgeJSLowerParameterWithRetain() + asOptional.bridgeJSLowerParameterWithRetain() } @_spi(BridgeJS) public static func bridgeJSLiftParameter( @@ -2165,13 +2165,13 @@ extension _BridgedAsOptional where Wrapped: _BridgedSwiftHeapObject { } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } extension _BridgedAsOptional where Wrapped == Float { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Float32) { - optionalRepresentation.bridgeJSLowerParameter() + asOptional.bridgeJSLowerParameter() } @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Float32) -> Self { @@ -2187,13 +2187,13 @@ extension _BridgedAsOptional where Wrapped == Float { } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } extension _BridgedAsOptional where Wrapped == Double { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Float64) { - optionalRepresentation.bridgeJSLowerParameter() + asOptional.bridgeJSLowerParameter() } @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Float64) -> Self { @@ -2209,13 +2209,13 @@ extension _BridgedAsOptional where Wrapped == Double { } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } extension _BridgedAsOptional where Wrapped: _BridgedSwiftCaseEnum { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { - optionalRepresentation.bridgeJSLowerParameter() + asOptional.bridgeJSLowerParameter() } @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ caseId: Int32) -> Self { @@ -2231,20 +2231,20 @@ extension _BridgedAsOptional where Wrapped: _BridgedSwiftCaseEnum { } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } extension _BridgedAsOptional where Wrapped: _BridgedSwiftTypeLoweredIntoVoidType { @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } extension _BridgedAsOptional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == String { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { - optionalRepresentation.bridgeJSLowerParameter() + asOptional.bridgeJSLowerParameter() } @_spi(BridgeJS) public static func bridgeJSLiftParameter( @@ -2264,14 +2264,14 @@ where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.Ra } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } extension _BridgedAsOptional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == Int { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { - optionalRepresentation.bridgeJSLowerParameter() + asOptional.bridgeJSLowerParameter() } @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Self { @@ -2287,7 +2287,7 @@ where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.Ra } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } @@ -2302,14 +2302,14 @@ where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.Ra } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } extension _BridgedAsOptional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == Float { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Float32) { - optionalRepresentation.bridgeJSLowerParameter() + asOptional.bridgeJSLowerParameter() } @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Float32) -> Self { @@ -2325,14 +2325,14 @@ where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.Ra } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } extension _BridgedAsOptional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == Double { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Float64) { - optionalRepresentation.bridgeJSLowerParameter() + asOptional.bridgeJSLowerParameter() } @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Float64) -> Self { @@ -2348,13 +2348,13 @@ where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.Ra } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } extension _BridgedAsOptional where Wrapped: _BridgedSwiftAssociatedValueEnum { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, caseId: Int32) { - optionalRepresentation.bridgeJSLowerParameter() + asOptional.bridgeJSLowerParameter() } @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ caseId: Int32) -> Self { @@ -2370,7 +2370,7 @@ extension _BridgedAsOptional where Wrapped: _BridgedSwiftAssociatedValueEnum { } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } @@ -2384,7 +2384,7 @@ extension _BridgedAsOptional where Wrapped: _BridgedSwiftStruct { } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - optionalRepresentation.bridgeJSLowerReturn() + asOptional.bridgeJSLowerReturn() } } @@ -2526,7 +2526,7 @@ extension _BridgedAsOptional where Wrapped: _BridgedSwiftDictionaryStackType { typealias DictionaryValue = Wrapped.DictionaryValue @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Int32 { - let opt = optionalRepresentation + let opt = asOptional if let dict = opt { dict.bridgeJSLowerReturn() return 1 diff --git a/Sources/JavaScriptKit/JSUndefinedOr.swift b/Sources/JavaScriptKit/JSUndefinedOr.swift index 82e218105..de7be09b4 100644 --- a/Sources/JavaScriptKit/JSUndefinedOr.swift +++ b/Sources/JavaScriptKit/JSUndefinedOr.swift @@ -1,17 +1,28 @@ +/// A wrapper that represents a JavaScript value of `Wrapped | undefined`. +/// +/// In BridgeJS, `Optional` is bridged as `Wrapped | null`. +/// Use `JSUndefinedOr` when the JavaScript API expects +/// `Wrapped | undefined` instead. @frozen public enum JSUndefinedOr { + /// The JavaScript value is `undefined`. case undefined + /// The JavaScript value is present and wrapped. case value(Wrapped) - /// Convenience accessor for the undefined case. - public static var undefinedValue: Self { .undefined } - + /// Creates a wrapper from a Swift optional. + /// + /// - Parameter optional: The optional value to wrap. + /// `nil` becomes ``undefined`` and a non-`nil` value becomes ``value(_:)``. @inlinable public init(optional: Wrapped?) { self = optional.map(Self.value) ?? .undefined } + /// Returns the wrapped value as a Swift optional. + /// + /// Returns `nil` when this value is ``undefined``. @inlinable - public var optionalRepresentation: Wrapped? { + public var asOptional: Wrapped? { switch self { case .undefined: return nil diff --git a/Tests/BridgeJSRuntimeTests/DictionaryTests.swift b/Tests/BridgeJSRuntimeTests/DictionaryTests.swift index 83ca72d04..ba702205d 100644 --- a/Tests/BridgeJSRuntimeTests/DictionaryTests.swift +++ b/Tests/BridgeJSRuntimeTests/DictionaryTests.swift @@ -57,7 +57,7 @@ final class DictionaryTests: XCTestCase { func testRoundTripOptionalDictionaryUndefined() throws { let some: JSUndefinedOr<[String: Int]> = .value(["n": 42]) - let undefined: JSUndefinedOr<[String: Int]> = .undefinedValue + let undefined: JSUndefinedOr<[String: Int]> = .undefined let returnedSome = try jsRoundTripUndefinedDictionary(some) switch returnedSome { diff --git a/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift b/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift index adfd51dea..454f5011d 100644 --- a/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift +++ b/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift @@ -23,7 +23,7 @@ final class OptionalSupportTests: XCTestCase { XCTFail("Expected defined value") } - let undefined = try jsRoundTripOptionalStringUndefined(.undefinedValue) + let undefined = try jsRoundTripOptionalStringUndefined(.undefined) if case .value = undefined { XCTFail("Expected undefined") } From 9eaefa6dd0210ad3e7f5e52bc23e5e2cc9a0acc5 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Tue, 10 Feb 2026 16:19:34 +0900 Subject: [PATCH 22/40] BridgeJS: Rename `BRIDGE_JS_PROFILING` to `BRIDGEJS_PROFILING` to be consistent with other environment variables used by BridgeJS. --- Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift b/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift index b36b3ec8c..3b784b732 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift @@ -327,7 +327,7 @@ private func inputSwiftFiles(targetDirectory: URL, positionalArguments: [String] extension Profiling { static func make() -> Profiling? { - guard let outputPath = ProcessInfo.processInfo.environment["BRIDGE_JS_PROFILING"] else { + guard let outputPath = ProcessInfo.processInfo.environment["BRIDGEJS_PROFILING"] else { return nil } let fd = open(outputPath, O_WRONLY | O_CREAT | O_TRUNC, 0o644) From 929af06dd07205def449f2063646f86466c15e28 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Tue, 10 Feb 2026 16:21:25 +0900 Subject: [PATCH 23/40] Merge pull request #616 from swiftwasm/katei/0736-bridgejs-diagnos BridgeJS: Include source-context in diagnostic messages --- Plugins/BridgeJS/Package.swift | 2 + .../BridgeJS/Sources/BridgeJSCore/Misc.swift | 150 ++++++++++++++- .../BridgeJSToolTests/DiagnosticsTests.swift | 182 ++++++++++++++++++ 3 files changed, 328 insertions(+), 6 deletions(-) create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift diff --git a/Plugins/BridgeJS/Package.swift b/Plugins/BridgeJS/Package.swift index 49aa161c9..2074a8a66 100644 --- a/Plugins/BridgeJS/Package.swift +++ b/Plugins/BridgeJS/Package.swift @@ -58,6 +58,8 @@ let package = Package( "BridgeJSCore", "BridgeJSLink", "TS2Swift", + .product(name: "SwiftParser", package: "swift-syntax"), + .product(name: "SwiftSyntax", package: "swift-syntax"), ], exclude: ["__Snapshots__", "Inputs"] ), diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift index 67f5170c4..9db11b14d 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift @@ -134,6 +134,7 @@ private enum JSON { // MARK: - DiagnosticError import SwiftSyntax +import class Foundation.ProcessInfo struct DiagnosticError: Error { let node: Syntax @@ -146,17 +147,154 @@ struct DiagnosticError: Error { self.hint = hint } - func formattedDescription(fileName: String) -> String { - let locationConverter = SourceLocationConverter(fileName: fileName, tree: node.root) - let location = locationConverter.location(for: node.position) - var description = "\(fileName):\(location.line):\(location.column): error: \(message)" + /// Formats the diagnostic error as a string. + /// + /// - Parameters: + /// - fileName: The name of the file to display in the output. + /// - colorize: Whether to colorize the output with ANSI escape sequences. + /// - Returns: The formatted diagnostic error string. + func formattedDescription(fileName: String, colorize: Bool = Self.shouldColorize) -> String { + let displayFileName = fileName == "-" ? "" : fileName + let converter = SourceLocationConverter(fileName: displayFileName, tree: node.root) + let startLocation = converter.location(for: node.positionAfterSkippingLeadingTrivia) + let endLocation = converter.location(for: node.endPositionBeforeTrailingTrivia) + + let sourceText = node.root.description + let lines = sourceText.split(omittingEmptySubsequences: false, whereSeparator: \.isNewline) + let startLineIndex = max(0, min(lines.count - 1, startLocation.line - 1)) + let mainLine = String(lines[startLineIndex]) + + let lineNumberWidth = max(3, String(lines.count).count) + + let header: String = { + guard colorize else { + return "\(displayFileName):\(startLocation.line):\(startLocation.column): error: \(message)" + } + return + "\(displayFileName):\(startLocation.line):\(startLocation.column): \(ANSI.boldRed)error: \(ANSI.boldDefault)\(message)\(ANSI.reset)" + }() + + let highlightStartColumn = min(max(1, startLocation.column), mainLine.utf8.count + 1) + let availableColumns = max(0, mainLine.utf8.count - (highlightStartColumn - 1)) + let rawHighlightLength: Int = { + guard availableColumns > 0 else { return 0 } + if startLocation.line == endLocation.line { + return max(1, min(endLocation.column - startLocation.column, availableColumns)) + } else { + return min(1, availableColumns) + } + }() + let highlightLength = min(rawHighlightLength, availableColumns) + + let formattedMainLine: String = { + guard colorize, highlightLength > 0 else { return mainLine } + + let startIndex = Self.index(atUTF8Offset: highlightStartColumn - 1, in: mainLine) + let endIndex = Self.index(atUTF8Offset: highlightStartColumn - 1 + highlightLength, in: mainLine) + + let prefix = String(mainLine[..= 0, lineIndex < lines.count else { continue } + descriptionParts.append( + Self.formatSourceLine( + number: lineIndex + 1, + text: String(lines[lineIndex]), + width: lineNumberWidth, + colorize: colorize + ) + ) + } + + descriptionParts.append( + Self.formatSourceLine( + number: startLocation.line, + text: formattedMainLine, + width: lineNumberWidth, + colorize: colorize + ) + ) + + let pointerSpacing = max(0, highlightStartColumn - 1) + let pointerMessage: String = { + let pointer = String(repeating: " ", count: pointerSpacing) + "`- " + guard colorize else { return pointer + "error: \(message)" } + return pointer + "\(ANSI.boldRed)error: \(ANSI.boldDefault)\(message)\(ANSI.reset)" + }() + descriptionParts.append( + Self.formatSourceLine( + number: nil, + text: pointerMessage, + width: lineNumberWidth, + colorize: colorize + ) + ) + + if startLineIndex + 1 < lines.count { + descriptionParts.append( + Self.formatSourceLine( + number: startLocation.line + 1, + text: String(lines[startLineIndex + 1]), + width: lineNumberWidth, + colorize: colorize + ) + ) + } + if let hint { - description += "\nHint: \(hint)" + descriptionParts.append("Hint: \(hint)") } - return description + + return descriptionParts.joined(separator: "\n") + } + + private static func formatSourceLine( + number: Int?, + text: String, + width: Int, + colorize: Bool + ) -> String { + let gutter: String + if let number { + let paddedNumber = String(repeating: " ", count: max(0, width - String(number).count)) + String(number) + gutter = colorize ? ANSI.cyan + paddedNumber + ANSI.reset : paddedNumber + } else { + gutter = String(repeating: " ", count: width) + } + return "\(gutter) | \(text)" + } + + private static var shouldColorize: Bool { + let env = ProcessInfo.processInfo.environment + let termIsDumb = env["TERM"] == "dumb" + return env["NO_COLOR"] == nil && !termIsDumb + } + + private static func index(atUTF8Offset offset: Int, in line: String) -> String.Index { + let clamped = max(0, min(offset, line.utf8.count)) + let utf8Index = line.utf8.index(line.utf8.startIndex, offsetBy: clamped) + // String.Index initializer is guaranteed to succeed because the UTF8 index comes from the same string. + return String.Index(utf8Index, within: line)! } } +private enum ANSI { + static let reset = "\u{001B}[0;0m" + static let boldRed = "\u{001B}[1;31m" + static let boldDefault = "\u{001B}[1;39m" + static let cyan = "\u{001B}[0;36m" + static let underline = "\u{001B}[4;39m" +} + // MARK: - BridgeJSCoreError public struct BridgeJSCoreError: Swift.Error, CustomStringConvertible { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift new file mode 100644 index 000000000..500a5db95 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift @@ -0,0 +1,182 @@ +import SwiftParser +import SwiftSyntax +import Testing + +@testable import BridgeJSCore + +@Suite struct DiagnosticsTests { + /// Returns the first parameter's type node from a function in the source (the first `@JS func`-like decl), for pinpointing diagnostics. + private func firstParameterTypeNode(source: String) -> TypeSyntax? { + let tree = Parser.parse(source: source) + for stmt in tree.statements { + if let funcDecl = stmt.item.as(FunctionDeclSyntax.self), + let firstParam = funcDecl.signature.parameterClause.parameters.first + { + return firstParam.type + } + } + return nil + } + + @Test + func diagnosticIncludesLocationSourceAndHint() throws { + let source = "@JS func foo(_ bar: A) {}\n" + let typeNode = try #require(firstParameterTypeNode(source: source)) + let diagnostic = DiagnosticError( + node: typeNode, + message: "Unsupported type 'A'.", + hint: "Only primitive types and types defined in the same module are allowed" + ) + let description = diagnostic.formattedDescription(fileName: "-", colorize: false) + let expectedPrefix = """ + :1:21: error: Unsupported type 'A'. + 1 | @JS func foo(_ bar: A) {} + | `- error: Unsupported type 'A'. + 2 | + """.trimmingCharacters(in: .whitespacesAndNewlines) + #expect(description.hasPrefix(expectedPrefix)) + #expect(description.contains("Hint: Only primitive types and types defined in the same module are allowed")) + } + + @Test + func diagnosticOmitsHintWhenNotProvided() throws { + let source = "@JS static func foo() {}\n" + let tree = Parser.parse(source: source) + let diagnostic = DiagnosticError( + node: tree, + message: "Top-level functions cannot be static", + hint: nil + ) + let description = diagnostic.formattedDescription(fileName: "-", colorize: false) + let expectedPrefix = """ + :1:1: error: Top-level functions cannot be static + 1 | @JS static func foo() {} + | `- error: Top-level functions cannot be static + 2 | + """.trimmingCharacters(in: .whitespacesAndNewlines) + #expect(description.hasPrefix(expectedPrefix)) + #expect(!description.contains("Hint:")) + } + + @Test + func diagnosticUsesGivenFileNameNotStdin() throws { + let source = "@JS func foo(_ bar: A) {}\n" + let typeNode = try #require(firstParameterTypeNode(source: source)) + let diagnostic = DiagnosticError( + node: typeNode, + message: "Unsupported type 'A'.", + hint: nil + ) + let description = diagnostic.formattedDescription(fileName: "Sources/Foo.swift", colorize: false) + #expect(description.hasPrefix("Sources/Foo.swift:1:21: error: Unsupported type 'A'.")) + } + + @Test + func diagnosticWithColorizeTrueIncludesANSISequences() throws { + let source = "@JS func foo(_ bar: A) {}\n" + let typeNode = try #require(firstParameterTypeNode(source: source)) + let diagnostic = DiagnosticError( + node: typeNode, + message: "Unsupported type 'A'.", + hint: nil + ) + let description = diagnostic.formattedDescription(fileName: "-", colorize: true) + let esc = "\u{001B}" + let boldRed = "\(esc)[1;31m" + let boldDefault = "\(esc)[1;39m" + let reset = "\(esc)[0;0m" + let cyan = "\(esc)[0;36m" + let underline = "\(esc)[4;39m" + let expected = + ":1:21: \(boldRed)error: \(boldDefault)Unsupported type 'A'.\(reset)\n" + + "\(cyan) 1\(reset) | @JS func foo(_ bar: \(underline)A\(reset)) {}\n" + + " | `- \(boldRed)error: \(boldDefault)Unsupported type 'A'.\(reset)\n" + + "\(cyan) 2\(reset) | " + #expect(description == expected) + } + + // MARK: - Context source lines + + @Test + func showsOnePreviousLineWhenErrorNotOnFirstLine() throws { + let source = """ + preamble + @JS func foo(_ bar: A) {} + """ + let typeNode = try #require(firstParameterTypeNode(source: source)) + let diagnostic = DiagnosticError(node: typeNode, message: "Unsupported type 'A'.", hint: nil) + let description = diagnostic.formattedDescription(fileName: "-", colorize: false) + #expect(description.contains(" 1 | preamble")) + #expect(description.contains(" 2 | @JS func foo(_ bar: A) {}")) + #expect(description.contains(":2:")) + } + + @Test + func showsThreePreviousLinesWhenAvailable() throws { + let source = """ + first + second + third + @JS func foo(_ bar: A) {} + """ + let typeNode = try #require(firstParameterTypeNode(source: source)) + let diagnostic = DiagnosticError(node: typeNode, message: "Unsupported type 'A'.", hint: nil) + let description = diagnostic.formattedDescription(fileName: "-", colorize: false) + #expect(description.contains(" 1 | first")) + #expect(description.contains(" 2 | second")) + #expect(description.contains(" 3 | third")) + #expect(description.contains(" 4 | @JS func foo(_ bar: A) {}")) + #expect(description.contains(":4:")) + } + + @Test + func capsContextAtThreePreviousLines() throws { + let source = """ + line0 + line1 + line2 + line3 + @JS func foo(_ bar: A) {} + """ + let typeNode = try #require(firstParameterTypeNode(source: source)) + let diagnostic = DiagnosticError(node: typeNode, message: "Unsupported type 'A'.", hint: nil) + let description = diagnostic.formattedDescription(fileName: "-", colorize: false) + #expect(!description.contains(" 1 | line0")) + #expect(description.contains(" 2 | line1")) + #expect(description.contains(" 3 | line2")) + #expect(description.contains(" 4 | line3")) + #expect(description.contains(" 5 | @JS func foo(_ bar: A) {}")) + #expect(description.contains(":5:")) + } + + @Test + func includesNextLineAfterErrorLine() throws { + let source = """ + @JS func foo( + _ bar: A + ) {} + """ + let typeNode = try #require(firstParameterTypeNode(source: source)) + let diagnostic = DiagnosticError(node: typeNode, message: "Unsupported type 'A'.", hint: nil) + let description = diagnostic.formattedDescription(fileName: "-", colorize: false) + #expect(description.contains(" 1 | @JS func foo(")) + #expect(description.contains(" 2 | _ bar: A")) + #expect(description.contains(" 3 | ) {}")) + #expect(description.contains(":2:")) + } + + @Test + func omitsNextLineWhenErrorIsOnLastLine() throws { + let source = """ + preamble + @JS func foo(_ bar: A) + """ + let typeNode = try #require(firstParameterTypeNode(source: source)) + let diagnostic = DiagnosticError(node: typeNode, message: "Unsupported type 'A'.", hint: nil) + let description = diagnostic.formattedDescription(fileName: "-", colorize: false) + #expect(description.contains(" 2 | @JS func foo(_ bar: A)")) + #expect(description.contains(":2:")) + // No line 3 in source, so output must not show a " 3 |" context line after the pointer + #expect(!description.contains(" 3 |")) + } +} From 63cb9af45a7b6b387cd8af50c83b3ad79e07fe29 Mon Sep 17 00:00:00 2001 From: Krzysztof Rodak Date: Tue, 10 Feb 2026 14:38:00 +0700 Subject: [PATCH 24/40] BridgeJS: Check generated TypeScript validity in test suites (#611) --- .github/workflows/test.yml | 4 ++++ .../__Snapshots__/BridgeJSLinkTests/tsconfig.json | 12 ++++++++++++ package.json | 3 ++- 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/tsconfig.json diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 68d6dac21..1e9060f19 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -69,6 +69,8 @@ jobs: git diff --exit-code Sources/JavaScriptKit/Runtime - run: swift test --package-path ./Plugins/PackageToJS - run: swift test --package-path ./Plugins/BridgeJS + - name: Validate BridgeJS TypeScript declarations + run: npm run check:bridgejs-dts test-bridgejs-against-swift-versions: name: Test BridgeJS against Swift versions @@ -90,6 +92,8 @@ jobs: node-version: '20' - name: Install TypeScript run: npm install + - name: Validate BridgeJS TypeScript declarations + run: npm run check:bridgejs-dts - name: Run BridgeJS tests # NOTE: Seems like the prebuilt SwiftSyntax binaries are not compatible with # non-macro dependents, so disable experimental prebuilts for now. diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/tsconfig.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/tsconfig.json new file mode 100644 index 000000000..277b2c578 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "strict": true, + "noEmit": true, + "skipLibCheck": false, + "target": "ES2020", + "module": "ES2020", + "moduleResolution": "node", + "lib": ["ES2020", "DOM"] + }, + "include": ["*.d.ts"] +} diff --git a/package.json b/package.json index 1f3f1871b..509cddde2 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "build:clean": "rm -rf Runtime/lib", "build:ts": "cd Runtime; rollup -c", "prepublishOnly": "npm run build", - "format": "prettier --write Runtime/src" + "format": "prettier --write Runtime/src", + "check:bridgejs-dts": "tsc --project Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/tsconfig.json" }, "keywords": [ "Swift", From b06a79bf9b10dbe868c1e8d2807fd6385f74929c Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Tue, 10 Feb 2026 17:27:30 +0900 Subject: [PATCH 25/40] BridgeJS: Allow executing TS2SwiftVitestTests on Xcode --- Plugins/BridgeJS/Sources/TS2Swift/TS2Swift.swift | 15 ++++++++------- .../BridgeJSToolTests/TS2SwiftVitestTests.swift | 13 +++++++++++-- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/Plugins/BridgeJS/Sources/TS2Swift/TS2Swift.swift b/Plugins/BridgeJS/Sources/TS2Swift/TS2Swift.swift index 795b7b390..6337dcf27 100644 --- a/Plugins/BridgeJS/Sources/TS2Swift/TS2Swift.swift +++ b/Plugins/BridgeJS/Sources/TS2Swift/TS2Swift.swift @@ -20,6 +20,12 @@ import BridgeJSCore import BridgeJSSkeleton #endif +#if os(Windows) +let PATH_SEPARATOR: Character = ";" +#else +let PATH_SEPARATOR: Character = ":" +#endif + internal func which( _ executable: String, environment: [String: String] = ProcessInfo.processInfo.environment @@ -39,13 +45,8 @@ internal func which( } } } - let pathSeparator: Character - #if os(Windows) - pathSeparator = ";" - #else - pathSeparator = ":" - #endif - let paths = environment["PATH"]?.split(separator: pathSeparator) ?? [] + + let paths = environment["PATH"]?.split(separator: PATH_SEPARATOR) ?? [] for path in paths { let url = URL(fileURLWithPath: String(path)).appendingPathComponent(executable) if checkCandidate(url) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/TS2SwiftVitestTests.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/TS2SwiftVitestTests.swift index bb3d2e0a4..f658b001f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/TS2SwiftVitestTests.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/TS2SwiftVitestTests.swift @@ -1,5 +1,6 @@ import Foundation import Testing +@testable import TS2Swift /// Runs the TS2Swift JavaScript test suite (Vitest) so that `swift test --package-path ./Plugins/BridgeJS` /// validates both the TypeScript ts2swift output and the Swift codegen. For fast iteration on ts2swift, @@ -17,8 +18,16 @@ import Testing .appendingPathComponent("TS2Swift") .appendingPathComponent("JavaScript") let process = Process() - process.executableURL = URL(fileURLWithPath: "/usr/bin/env") - var arguments = ["npm", "run", "test"] + guard let npmExecutable = which("npm"), let nodeExecutable = which("node") else { + Issue.record("No \"npm\" command found in your system") + return + } + process.executableURL = npmExecutable + var environment = ProcessInfo.processInfo.environment + environment["PATH"] = + "\(nodeExecutable.deletingLastPathComponent().path)\(PATH_SEPARATOR) \(environment["PATH"] ?? "")" + process.environment = environment + var arguments = ["run", "test"] if ProcessInfo.processInfo.environment["UPDATE_SNAPSHOTS"] != nil { arguments.append(contentsOf: ["--", "--update"]) } From cb7b6a92d9127c98b326214ed7f7ac3ced50ad10 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Wed, 11 Feb 2026 18:15:32 +0900 Subject: [PATCH 26/40] BridgeJS: Remove parsing API usage from JSSetterMacro --- Plugins/BridgeJS/Sources/BridgeJSMacros/JSSetterMacro.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSMacros/JSSetterMacro.swift b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSSetterMacro.swift index ba171e8eb..4d32db449 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSMacros/JSSetterMacro.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSSetterMacro.swift @@ -54,7 +54,7 @@ extension JSSetterMacro: BodyMacro { firstName: .wildcardToken(trailingTrivia: .space), secondName: .identifier("value"), colon: .colonToken(trailingTrivia: .space), - type: TypeSyntax(stringLiteral: "<#Type#>") + type: IdentifierTypeSyntax(name: TokenSyntax(.identifier("<#Type#>"), presence: .present)) ) let newClause = FunctionParameterClauseSyntax( leftParen: .leftParenToken(), From 9162fa0cebca2c7e35a135e0819f8977b92dbf97 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Wed, 11 Feb 2026 18:32:46 +0900 Subject: [PATCH 27/40] BridgeJS: Remove BasicFormat usage in ExportSwift --- Benchmarks/Sources/Generated/BridgeJS.swift | 83 ++- .../Sources/BridgeJSCore/ClosureCodegen.swift | 133 ++-- .../Sources/BridgeJSCore/ExportSwift.swift | 612 ++++++++++-------- .../Sources/BridgeJSCore/ImportTS.swift | 584 +++++------------ .../Sources/BridgeJSUtilities/Utilities.swift | 6 + .../BridgeJSCodegenTests/ArrayTypes.swift | 100 +-- .../BridgeJSCodegenTests/Async.swift | 14 +- .../EnumAssociatedValue.swift | 66 +- .../ImportedTypeInExportedInterface.swift | 28 +- .../BridgeJSCodegenTests/JSValue.swift | 5 +- .../BridgeJSCodegenTests/Protocol.swift | 12 +- .../BridgeJSCodegenTests/SwiftStruct.swift | 13 +- .../Generated/BridgeJS.swift | 305 ++++----- 13 files changed, 880 insertions(+), 1081 deletions(-) diff --git a/Benchmarks/Sources/Generated/BridgeJS.swift b/Benchmarks/Sources/Generated/BridgeJS.swift index 5a480694c..515d3a531 100644 --- a/Benchmarks/Sources/Generated/BridgeJS.swift +++ b/Benchmarks/Sources/Generated/BridgeJS.swift @@ -312,7 +312,7 @@ extension Person: _BridgedSwiftStruct { self.address.bridgeJSLowerReturn() let __bjs_isSome_email = self.email != nil if let __bjs_unwrapped_email = self.email { - __bjs_unwrapped_email.bridgeJSLowerStackReturn() + __bjs_unwrapped_email.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_email ? 1 : 0) } @@ -1569,12 +1569,12 @@ public func _bjs_ArrayRoundtrip_takeNestedIntArray(_ _self: UnsafeMutableRawPoin let __count = Int(_swift_js_pop_i32()) var __result: [[Int]] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append([Int].bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) #else fatalError("Only available on WebAssembly") #endif @@ -1586,7 +1586,8 @@ public func _bjs_ArrayRoundtrip_makeNestedIntArray(_ _self: UnsafeMutableRawPoin #if arch(wasm32) let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeNestedIntArray() for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn()} + __bjs_elem_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -1601,14 +1602,15 @@ public func _bjs_ArrayRoundtrip_roundtripNestedIntArray(_ _self: UnsafeMutableRa let __count = Int(_swift_js_pop_i32()) var __result: [[Int]] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append([Int].bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn()} + __bjs_elem_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -1623,12 +1625,12 @@ public func _bjs_ArrayRoundtrip_takeNestedPointArray(_ _self: UnsafeMutableRawPo let __count = Int(_swift_js_pop_i32()) var __result: [[Point]] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append([Point].bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) #else fatalError("Only available on WebAssembly") #endif @@ -1640,7 +1642,8 @@ public func _bjs_ArrayRoundtrip_makeNestedPointArray(_ _self: UnsafeMutableRawPo #if arch(wasm32) let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeNestedPointArray() for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn()} + __bjs_elem_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -1655,14 +1658,15 @@ public func _bjs_ArrayRoundtrip_roundtripNestedPointArray(_ _self: UnsafeMutable let __count = Int(_swift_js_pop_i32()) var __result: [[Point]] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append([Point].bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn()} + __bjs_elem_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -1677,12 +1681,12 @@ public func _bjs_ArrayRoundtrip_takeOptionalIntArray(_ _self: UnsafeMutableRawPo let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Optional.bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) #else fatalError("Only available on WebAssembly") #endif @@ -1696,8 +1700,10 @@ public func _bjs_ArrayRoundtrip_makeOptionalIntArray(_ _self: UnsafeMutableRawPo for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -1712,17 +1718,19 @@ public func _bjs_ArrayRoundtrip_roundtripOptionalIntArray(_ _self: UnsafeMutable let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Optional.bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -1737,12 +1745,12 @@ public func _bjs_ArrayRoundtrip_takeOptionalPointArray(_ _self: UnsafeMutableRaw let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Optional.bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) #else fatalError("Only available on WebAssembly") #endif @@ -1756,8 +1764,10 @@ public func _bjs_ArrayRoundtrip_makeOptionalPointArray(_ _self: UnsafeMutableRaw for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.bridgeJSLowerReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -1772,17 +1782,19 @@ public func _bjs_ArrayRoundtrip_roundtripOptionalPointArray(_ _self: UnsafeMutab let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Optional.bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.bridgeJSLowerReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -1799,7 +1811,7 @@ public func _bjs_ArrayRoundtrip_takeOptionalArray(_ _self: UnsafeMutableRawPoint } else { return [Int].bridgeJSLiftParameter() } - }()) + }()) #else fatalError("Only available on WebAssembly") #endif @@ -1812,7 +1824,8 @@ public func _bjs_ArrayRoundtrip_makeOptionalArraySome(_ _self: UnsafeMutableRawP let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeOptionalArraySome() let __bjs_isSome_ret = ret != nil if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn()} + __bjs_unwrapped_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) #else fatalError("Only available on WebAssembly") @@ -1826,7 +1839,8 @@ public func _bjs_ArrayRoundtrip_makeOptionalArrayNone(_ _self: UnsafeMutableRawP let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeOptionalArrayNone() let __bjs_isSome_ret = ret != nil if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn()} + __bjs_unwrapped_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) #else fatalError("Only available on WebAssembly") @@ -1843,10 +1857,11 @@ public func _bjs_ArrayRoundtrip_roundtripOptionalArray(_ _self: UnsafeMutableRaw } else { return [Int].bridgeJSLiftParameter() } - }()) + }()) let __bjs_isSome_ret = ret != nil if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn()} + __bjs_unwrapped_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) #else fatalError("Only available on WebAssembly") diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift index 49f2b99bf..eefc63a7e 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift @@ -4,6 +4,9 @@ import SwiftSyntaxBuilder #if canImport(BridgeJSSkeleton) import BridgeJSSkeleton #endif +#if canImport(BridgeJSUtilities) +import BridgeJSUtilities +#endif public struct ClosureCodegen { public init() {} @@ -41,9 +44,6 @@ public struct ClosureCodegen { try builder.call(returnType: signature.returnType) try builder.liftReturnValue(returnType: signature.returnType) - // Get the body code - let bodyCode = builder.getBody() - // Generate extern declaration using CallJSEmission let externDecl = builder.renderImportDecl() @@ -58,79 +58,42 @@ public struct ClosureCodegen { #endif """ - let helperEnumDecl = EnumDeclSyntax( - modifiers: DeclModifierListSyntax { - DeclModifierSyntax(name: .keyword(.private)) - }, - name: .identifier(helperName), - memberBlockBuilder: { - DeclSyntax( - FunctionDeclSyntax( - modifiers: DeclModifierListSyntax { - DeclModifierSyntax(name: .keyword(.static)) - }, - name: .identifier("bridgeJSLift"), - signature: FunctionSignatureSyntax( - parameterClause: FunctionParameterClauseSyntax { - FunctionParameterSyntax( - firstName: .wildcardToken(), - secondName: .identifier("callbackId"), - colon: .colonToken(), - type: IdentifierTypeSyntax(name: .identifier("Int32")) - ) - }, - returnClause: ReturnClauseSyntax( - arrow: .arrowToken(), - type: IdentifierTypeSyntax(name: .identifier(swiftClosureType)) - ) - ), - body: CodeBlockSyntax { - "let callback = JSObject.bridgeJSLiftParameter(callbackId)" - ReturnStmtSyntax( - expression: ClosureExprSyntax( - leftBrace: .leftBraceToken(), - signature: ClosureSignatureSyntax( - capture: ClosureCaptureClauseSyntax( - leftSquare: .leftSquareToken(), - items: ClosureCaptureListSyntax { - #if canImport(SwiftSyntax602) - ClosureCaptureSyntax( - name: .identifier("", presence: .missing), - initializer: InitializerClauseSyntax( - equal: .equalToken(presence: .missing), - nil, - value: ExprSyntax("callback") - ), - trailingTrivia: nil - ) - #else - ClosureCaptureSyntax( - expression: ExprSyntax("callback") - ) - #endif - }, - rightSquare: .rightSquareToken() - ), - parameterClause: .simpleInput( - ClosureShorthandParameterListSyntax { - for (index, _) in signature.parameters.enumerated() { - ClosureShorthandParameterSyntax(name: .identifier("param\(index)")) - } - } - ), - inKeyword: .keyword(.in) - ), - statements: CodeBlockItemListSyntax { - SwiftCodePattern.buildWasmConditionalCompilation(wasmBody: bodyCode.statements) - }, - rightBrace: .rightBraceToken() - ) - ) + let helperEnumDeclPrinter = CodeFragmentPrinter() + helperEnumDeclPrinter.write("private enum \(helperName) {") + helperEnumDeclPrinter.indent { + helperEnumDeclPrinter.write("static func bridgeJSLift(_ callbackId: Int32) -> \(swiftClosureType) {") + helperEnumDeclPrinter.indent { + helperEnumDeclPrinter.write("let callback = JSObject.bridgeJSLiftParameter(callbackId)") + let parameters: String + if signature.parameters.isEmpty { + parameters = "" + } else if signature.parameters.count == 1 { + parameters = " param0" + } else { + parameters = + " (" + + signature.parameters.enumerated().map { index, param in + "param\(index)" + }.joined(separator: ", ") + ")" + } + helperEnumDeclPrinter.write("return { [callback]\(parameters) in") + helperEnumDeclPrinter.indent { + SwiftCodePattern.buildWasmConditionalCompilation( + printer: helperEnumDeclPrinter, + wasmBody: { printer in + printer.write(lines: builder.body.lines) } ) - ) + } + helperEnumDeclPrinter.write("}") + } - ) + helperEnumDeclPrinter.write("}") + } + helperEnumDeclPrinter.write("}") + + let helperEnumDecl: DeclSyntax = "\(raw: helperEnumDeclPrinter.lines.joined(separator: "\n"))" + let typedClosureExtension: DeclSyntax = """ extension JSTypedClosure where Signature == \(raw: swiftClosureType) { init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping \(raw: swiftClosureType)) { @@ -145,7 +108,7 @@ public struct ClosureCodegen { """ return [ - externDecl, makeClosureExternDecl, DeclSyntax(helperEnumDecl), typedClosureExtension, + externDecl, makeClosureExternDecl, helperEnumDecl, typedClosureExtension, ] } @@ -199,24 +162,20 @@ public struct ClosureCodegen { returnType: abiReturnWasmType ) - // Build body - let body = CodeBlockItemListSyntax { - "let closure = Unmanaged<\(raw: boxType)>.fromOpaque(boxPtr).takeUnretainedValue().closure" + // Build function declaration using helper + let funcDecl = SwiftCodePattern.buildExposedFunctionDecl( + abiName: abiName, + signature: funcSignature + ) { printer in + printer.write("let closure = Unmanaged<\(boxType)>.fromOpaque(boxPtr).takeUnretainedValue().closure") if signature.returnType == .void { - closureCallExpr + printer.write(closureCallExpr.description) } else { - "let result = \(closureCallExpr)" - "return result.bridgeJSLowerReturn()" + printer.write("let result = \(closureCallExpr)") + printer.write("return result.bridgeJSLowerReturn()") } } - // Build function declaration using helper - let funcDecl = SwiftCodePattern.buildExposedFunctionDecl( - abiName: abiName, - signature: funcSignature, - body: body - ) - return DeclSyntax(funcDecl) } diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index 913bc076b..2d31cd212 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -91,8 +91,7 @@ public class ExportSwift { } } return withSpan("Format Export Glue") { - let format = BasicFormat() - return decls.map { $0.formatted(using: format).description }.joined(separator: "\n\n") + return decls.map { $0.description }.joined(separator: "\n\n") } } @@ -423,9 +422,10 @@ public class ExportSwift { // Build function declaration using helper function let funcDecl = SwiftCodePattern.buildExposedFunctionDecl( abiName: abiName, - signature: signature, - body: body - ) + signature: signature + ) { printer in + printer.write(multilineString: body.description) + } return DeclSyntax(funcDecl) } @@ -715,11 +715,10 @@ public class ExportSwift { signature: SwiftSignatureBuilder.buildABIFunctionSignature( abiParameters: [("pointer", .pointer)], returnType: nil - ), - body: CodeBlockItemListSyntax { - "Unmanaged<\(raw: klass.swiftCallName)>.fromOpaque(pointer).release()" - } - ) + ) + ) { printer in + printer.write("Unmanaged<\(klass.swiftCallName)>.fromOpaque(pointer).release()") + } decls.append(DeclSyntax(funcDecl)) } @@ -763,34 +762,29 @@ public class ExportSwift { returnType: .i32 ) - // Build extern function declaration (no body) - let externFuncDecl = SwiftCodePattern.buildExternFunctionDecl( - moduleName: moduleName, - abiName: externFunctionName, - functionName: wrapFunctionName, - signature: funcSignature - ) - - // Build stub function declaration (with fatalError body) - let stubFuncDecl = FunctionDeclSyntax( - modifiers: DeclModifierListSyntax { - DeclModifierSyntax(name: .keyword(.fileprivate)) + let externDeclPrinter = CodeFragmentPrinter() + SwiftCodePattern.buildWasmConditionalCompilationDecls( + printer: externDeclPrinter, + wasmDecl: { printer in + SwiftCodePattern.buildExternFunctionDecl( + printer: printer, + moduleName: moduleName, + abiName: externFunctionName, + functionName: wrapFunctionName, + signature: funcSignature + ) }, - funcKeyword: .keyword(.func), - name: .identifier(wrapFunctionName), - signature: funcSignature, - body: CodeBlockSyntax { - "fatalError(\"Only available on WebAssembly\")" + elseDecl: { printer in + printer.write( + multilineString: """ + fileprivate func \(wrapFunctionName)\(funcSignature) { + fatalError("Only available on WebAssembly") + } + """ + ) } ) - - // Use helper function for conditional compilation - let externDecl = DeclSyntax( - SwiftCodePattern.buildWasmConditionalCompilationDecls( - wasmDecl: DeclSyntax(externFuncDecl), - elseDecl: DeclSyntax(stubFuncDecl) - ) - ) + let externDecl: DeclSyntax = "\(raw: externDeclPrinter.lines.joined(separator: "\n"))" return [extensionDecl, externDecl] } } @@ -1035,9 +1029,9 @@ struct StackCodegen { accessor: String, varPrefix: String ) -> [CodeBlockItemSyntax] { - var statements: [CodeBlockItemSyntax] = [] + var statements: [String] = [] let elementVarName = "__bjs_elem_\(varPrefix)" - statements.append("for \(raw: elementVarName) in \(raw: accessor) {") + statements.append("for \(elementVarName) in \(accessor) {") let elementStatements = lowerStatements( for: elementType, @@ -1045,12 +1039,13 @@ struct StackCodegen { varPrefix: "\(varPrefix)_elem" ) for stmt in elementStatements { - statements.append(stmt) + statements.append(stmt.description) } statements.append("}") - statements.append("_swift_js_push_i32(Int32(\(raw: accessor).count))") - return statements + statements.append("_swift_js_push_i32(Int32(\(accessor).count))") + let parsed: CodeBlockItemListSyntax = "\(raw: statements.joined(separator: "\n"))" + return Array(parsed) } private func lowerDictionaryStatements( @@ -1117,9 +1112,9 @@ struct StackCodegen { accessor: String, varPrefix: String ) -> [CodeBlockItemSyntax] { - var statements: [CodeBlockItemSyntax] = [] - statements.append("let __bjs_isSome_\(raw: varPrefix) = \(raw: accessor) != nil") - statements.append("if let __bjs_unwrapped_\(raw: varPrefix) = \(raw: accessor) {") + var statements: [String] = [] + statements.append("let __bjs_isSome_\(varPrefix) = \(accessor) != nil") + statements.append("if let __bjs_unwrapped_\(varPrefix) = \(accessor) {") let innerStatements = lowerUnwrappedOptionalStatements( wrappedType: wrappedType, @@ -1127,12 +1122,13 @@ struct StackCodegen { varPrefix: varPrefix ) for stmt in innerStatements { - statements.append(stmt) + statements.append(stmt.description) } statements.append("}") - statements.append("_swift_js_push_i32(__bjs_isSome_\(raw: varPrefix) ? 1 : 0)") - return statements + statements.append("_swift_js_push_i32(__bjs_isSome_\(varPrefix) ? 1 : 0)") + let parsed: CodeBlockItemListSyntax = "\(raw: statements.joined(separator: "\n"))" + return Array(parsed) } private func lowerUnwrappedOptionalStatements( @@ -1186,104 +1182,151 @@ struct EnumCodegen { } private func renderCaseEnumHelpers(_ enumDef: ExportedEnum) -> DeclSyntax { - let typeName = enumDef.swiftCallName - var initCases: [String] = [] - var valueCases: [String] = [] - for (index, enumCase) in enumDef.cases.enumerated() { - initCases.append("case \(index): self = .\(enumCase.name)") - valueCases.append("case .\(enumCase.name): return \(index)") - } - let initSwitch = (["switch bridgeJSRawValue {"] + initCases + ["default: return nil", "}"]).joined( - separator: "\n" - ) - let valueSwitch = (["switch self {"] + valueCases + ["}"]).joined(separator: "\n") + let printer = CodeFragmentPrinter() + printer.write("extension \(enumDef.swiftCallName): _BridgedSwiftCaseEnum {") + printer.indent { + printer.write( + multilineString: """ + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> \(enumDef.swiftCallName) { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> \(enumDef.swiftCallName) { + return \(enumDef.swiftCallName)(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } - return """ - extension \(raw: typeName): _BridgedSwiftCaseEnum { - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { - return bridgeJSRawValue - } - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> \(raw: typeName) { - return bridgeJSLiftParameter(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 bridgeJSLowerParameter() + """ + ) + printer.nextLine() + + printer.write("private init?(bridgeJSRawValue: Int32) {") + printer.indent { + printer.write("switch bridgeJSRawValue {") + for (index, enumCase) in enumDef.cases.enumerated() { + printer.write("case \(index):") + printer.indent { + printer.write("self = .\(enumCase.name)") + } } - - private init?(bridgeJSRawValue: Int32) { - \(raw: initSwitch) + printer.write("default:") + printer.indent { + printer.write("return nil") } - - private var bridgeJSRawValue: Int32 { - \(raw: valueSwitch) + printer.write("}") + } + printer.write("}") + printer.nextLine() + + printer.write("private var bridgeJSRawValue: Int32 {") + printer.indent { + printer.write("switch self {") + for (index, enumCase) in enumDef.cases.enumerated() { + printer.write("case .\(enumCase.name):") + printer.indent { + printer.write("return \(index)") + } } + printer.write("}") } - """ + printer.write("}") + } + printer.write("}") + return "\(raw: printer.lines.joined(separator: "\n"))" } private func renderRawValueEnumHelpers(_ enumDef: ExportedEnum) -> DeclSyntax { let typeName = enumDef.swiftCallName guard enumDef.rawType != nil else { return """ - extension \(raw: typeName): _BridgedSwiftEnumNoPayload {} + extension \(raw: typeName): _BridgedSwiftEnumNoPayload { + } """ } // When rawType is present, conform to _BridgedSwiftRawValueEnum which provides // default implementations for _BridgedSwiftStackType methods via protocol extension. return """ - extension \(raw: typeName): _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum {} + extension \(raw: typeName): _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { + } """ } private func renderAssociatedValueEnumHelpers(_ enumDef: ExportedEnum) -> DeclSyntax { let typeName = enumDef.swiftCallName - return """ - extension \(raw: typeName): _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> \(raw: typeName) { - switch caseId { - \(raw: generateStackLiftSwitchCases(enumDef: enumDef).joined(separator: "\n")) - default: fatalError("Unknown \(raw: typeName) case ID: \\(caseId)") - } + let printer = CodeFragmentPrinter() + printer.write("extension \(typeName): _BridgedSwiftAssociatedValueEnum {") + printer.indent { + printer.write("private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> \(typeName) {") + printer.indent { + printer.write("switch caseId {") + generateStackLiftSwitchCases(printer: printer, enumDef: enumDef) + printer.write("default:") + printer.indent { + printer.write("fatalError(\"Unknown \(typeName) case ID: \\(caseId)\")") } + printer.write("}") + } + printer.write("}") + printer.nextLine() - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { - switch self { - \(raw: generateLowerParameterSwitchCases(enumDef: enumDef).joined(separator: "\n")) - } - } + printer.write("// MARK: Protocol Export") + printer.nextLine() - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> \(raw: typeName) { - return _bridgeJSLiftFromCaseId(caseId) - } + printer.write("@_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 {") + printer.indent { + printer.write("switch self {") + generateLowerParameterSwitchCases(printer: printer, enumDef: enumDef) + printer.write("}") + } + printer.write("}") + printer.nextLine() - // MARK: ExportSwift + printer.write( + multilineString: """ + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> \(typeName) { + return _bridgeJSLiftFromCaseId(caseId) + } + """ + ) + printer.nextLine() - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> \(raw: typeName) { - return _bridgeJSLiftFromCaseId(caseId) - } + printer.write("// MARK: ExportSwift") + printer.nextLine() - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - \(raw: generateReturnSwitchCases(enumDef: enumDef).joined(separator: "\n")) + printer.write( + multilineString: """ + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> \(typeName) { + return _bridgeJSLiftFromCaseId(caseId) } - } + """ + ) + printer.nextLine() + + printer.write("@_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() {") + printer.indent { + printer.write("switch self {") + generateReturnSwitchCases(printer: printer, enumDef: enumDef) + printer.write("}") } - """ + printer.write("}") + } + printer.write("}") + return "\(raw: printer.lines.joined(separator: "\n"))" } - private func generateStackLiftSwitchCases(enumDef: ExportedEnum) -> [String] { - var cases: [String] = [] + private func generateStackLiftSwitchCases(printer: CodeFragmentPrinter, enumDef: ExportedEnum) { for (caseIndex, enumCase) in enumDef.cases.enumerated() { if enumCase.associatedValues.isEmpty { - cases.append("case \(caseIndex): return .\(enumCase.name)") + printer.write("case \(caseIndex):") + printer.indent { + printer.write("return .\(enumCase.name)") + } } else { - var lines: [String] = [] - lines.append("case \(caseIndex):") + printer.write("case \(caseIndex):") let argList = enumCase.associatedValues.map { associatedValue in let labelPrefix: String if let label = associatedValue.label { @@ -1294,17 +1337,17 @@ struct EnumCodegen { let liftExpr = stackCodegen.liftExpression(for: associatedValue.type) return "\(labelPrefix)\(liftExpr)" } - lines.append("return .\(enumCase.name)(\(argList.joined(separator: ", ")))") - cases.append(lines.joined(separator: "\n")) + printer.indent { + printer.write("return .\(enumCase.name)(\(argList.joined(separator: ", ")))") + } } } - return cases } private func generatePayloadPushingCode( + printer: CodeFragmentPrinter, associatedValues: [AssociatedValue] - ) -> [String] { - var bodyLines: [String] = [] + ) { for (index, associatedValue) in associatedValues.enumerated() { let paramName = associatedValue.label ?? "param\(index)" let statements = stackCodegen.lowerStatements( @@ -1312,51 +1355,50 @@ struct EnumCodegen { accessor: paramName, varPrefix: paramName ) - for stmt in statements { - bodyLines.append(stmt.description) - } + printer.write(multilineString: CodeBlockItemListSyntax(statements).description) } - return bodyLines } - private func generateLowerParameterSwitchCases(enumDef: ExportedEnum) -> [String] { - var cases: [String] = [] + private func generateLowerParameterSwitchCases(printer: CodeFragmentPrinter, enumDef: ExportedEnum) { for (caseIndex, enumCase) in enumDef.cases.enumerated() { if enumCase.associatedValues.isEmpty { - cases.append("case .\(enumCase.name):") - cases.append("return Int32(\(caseIndex))") + printer.write("case .\(enumCase.name):") + printer.indent { + printer.write("return Int32(\(caseIndex))") + } } else { - let payloadCode = generatePayloadPushingCode(associatedValues: enumCase.associatedValues) let pattern = enumCase.associatedValues.enumerated() .map { index, associatedValue in "let \(associatedValue.label ?? "param\(index)")" } .joined(separator: ", ") - cases.append("case .\(enumCase.name)(\(pattern)):") - cases.append(contentsOf: payloadCode) - cases.append("return Int32(\(caseIndex))") + printer.write("case .\(enumCase.name)(\(pattern)):") + printer.indent { + generatePayloadPushingCode(printer: printer, associatedValues: enumCase.associatedValues) + printer.write("return Int32(\(caseIndex))") + } } } - return cases } - private func generateReturnSwitchCases(enumDef: ExportedEnum) -> [String] { - var cases: [String] = [] + private func generateReturnSwitchCases(printer: CodeFragmentPrinter, enumDef: ExportedEnum) { for (caseIndex, enumCase) in enumDef.cases.enumerated() { if enumCase.associatedValues.isEmpty { - cases.append("case .\(enumCase.name):") - cases.append("_swift_js_push_tag(Int32(\(caseIndex)))") + printer.write("case .\(enumCase.name):") + printer.indent { + printer.write("_swift_js_push_tag(Int32(\(caseIndex)))") + } } else { let pattern = enumCase.associatedValues.enumerated() .map { index, associatedValue in "let \(associatedValue.label ?? "param\(index)")" } .joined(separator: ", ") - cases.append("case .\(enumCase.name)(\(pattern)):") - let payloadCode = generatePayloadPushingCode(associatedValues: enumCase.associatedValues) - cases.append(contentsOf: payloadCode) - // Push tag AFTER payloads so it's popped first (LIFO) by the JS lift function. - // This ensures nested enum tags don't overwrite the outer tag. - cases.append("_swift_js_push_tag(Int32(\(caseIndex)))") + printer.write("case .\(enumCase.name)(\(pattern)):") + printer.indent { + generatePayloadPushingCode(printer: printer, associatedValues: enumCase.associatedValues) + // Push tag AFTER payloads so it's popped first (LIFO) by the JS lift function. + // This ensures nested enum tags don't overwrite the outer tag. + printer.write("_swift_js_push_tag(Int32(\(caseIndex)))") + } } } - return cases } } @@ -1367,40 +1409,60 @@ struct StructCodegen { func renderStructHelpers(_ structDef: ExportedStruct) -> [DeclSyntax] { let typeName = structDef.swiftCallName - let liftCode = generateStructLiftCode(structDef: structDef) - let lowerCode = generateStructLowerCode(structDef: structDef) - let accessControl = structDef.explicitAccessControl.map { "\($0) " } ?? "" let lowerExternName = "swift_js_struct_lower_\(structDef.name)" let liftExternName = "swift_js_struct_lift_\(structDef.name)" let lowerFunctionName = "_bjs_struct_lower_\(structDef.name)" let liftFunctionName = "_bjs_struct_lift_\(structDef.name)" - let bridgedStructExtension: DeclSyntax = """ - extension \(raw: typeName): _BridgedSwiftStruct { - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> \(raw: typeName) { - \(raw: liftCode.joined(separator: "\n")) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - \(raw: lowerCode.joined(separator: "\n")) - } - - \(raw: accessControl)init(unsafelyCopying jsObject: JSObject) { - let __bjs_cleanupId = \(raw: lowerFunctionName)(jsObject.bridgeJSLowerParameter()) - defer { _swift_js_struct_cleanup(__bjs_cleanupId) } - self = Self.bridgeJSLiftParameter() - } + let printer = CodeFragmentPrinter() + printer.write("extension \(typeName): _BridgedSwiftStruct {") + printer.indent { + printer.write("@_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> \(typeName) {") + printer.indent { + printer.write(lines: generateStructLiftCode(structDef: structDef)) + } + printer.write("}") + printer.nextLine() - \(raw: accessControl)func toJSObject() -> JSObject { - let __bjs_self = self - __bjs_self.bridgeJSLowerReturn() - return JSObject(id: UInt32(bitPattern: \(raw: liftFunctionName)())) - } + printer.write("@_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() {") + printer.indent { + printer.write(lines: generateStructLowerCode(structDef: structDef)) } - """ + printer.write("}") + printer.nextLine() + + let accessControl = structDef.explicitAccessControl.map { "\($0) " } ?? "" + printer.write( + multilineString: """ + \(accessControl)init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = \(lowerFunctionName)(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + """ + ) + printer.nextLine() + + printer.write( + multilineString: """ + \(accessControl)func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: \(liftFunctionName)())) + } + """ + ) + } + printer.write("}") - let lowerExternDecl = Self.renderStructExtern( + let bridgedStructExtension: DeclSyntax = "\(raw: printer.lines.joined(separator: "\n"))" + + let lowerExternDeclPrinter = CodeFragmentPrinter() + Self.renderStructExtern( + printer: lowerExternDeclPrinter, externName: lowerExternName, functionName: lowerFunctionName, signature: SwiftSignatureBuilder.buildABIFunctionSignature( @@ -1408,7 +1470,9 @@ struct StructCodegen { returnType: .i32 ) ) - let liftExternDecl = Self.renderStructExtern( + let liftExternDeclPrinter = CodeFragmentPrinter() + Self.renderStructExtern( + printer: liftExternDeclPrinter, externName: liftExternName, functionName: liftFunctionName, signature: SwiftSignatureBuilder.buildABIFunctionSignature( @@ -1417,39 +1481,39 @@ struct StructCodegen { ) ) - return [bridgedStructExtension, lowerExternDecl, liftExternDecl] + return [ + bridgedStructExtension, "\(raw: lowerExternDeclPrinter.lines.joined(separator: "\n"))", + "\(raw: liftExternDeclPrinter.lines.joined(separator: "\n"))", + ] } private static func renderStructExtern( + printer: CodeFragmentPrinter, externName: String, functionName: String, - signature: FunctionSignatureSyntax - ) -> DeclSyntax { - let externFuncDecl = SwiftCodePattern.buildExternFunctionDecl( - moduleName: "bjs", - abiName: externName, - functionName: functionName, - signature: signature - ) - - let stubFuncDecl = FunctionDeclSyntax( - modifiers: DeclModifierListSyntax { - DeclModifierSyntax(name: .keyword(.fileprivate)) + signature: String + ) { + SwiftCodePattern.buildWasmConditionalCompilationDecls( + printer: printer, + wasmDecl: { printer in + SwiftCodePattern.buildExternFunctionDecl( + printer: printer, + moduleName: "bjs", + abiName: externName, + functionName: functionName, + signature: signature + ) }, - funcKeyword: .keyword(.func), - name: .identifier(functionName), - signature: signature, - body: CodeBlockSyntax { - "fatalError(\"Only available on WebAssembly\")" + elseDecl: { printer in + printer.write( + multilineString: """ + fileprivate func \(functionName)\(signature) { + fatalError("Only available on WebAssembly") + } + """ + ) } ) - - return DeclSyntax( - SwiftCodePattern.buildWasmConditionalCompilationDecls( - wasmDecl: DeclSyntax(externFuncDecl), - elseDecl: DeclSyntax(stubFuncDecl) - ) - ) } private func generateStructLiftCode(structDef: ExportedStruct) -> [String] { @@ -1469,7 +1533,7 @@ struct StructCodegen { } private func generateStructLowerCode(structDef: ExportedStruct) -> [String] { - var lines: [String] = [] + let printer = CodeFragmentPrinter() let instanceProps = structDef.properties.filter { !$0.isStatic } for property in instanceProps { @@ -1479,12 +1543,10 @@ struct StructCodegen { accessor: accessor, varPrefix: property.name ) - for stmt in statements { - lines.append(stmt.description) - } + printer.write(multilineString: CodeBlockItemListSyntax(statements).description) } - return lines + return printer.lines } } @@ -1495,7 +1557,7 @@ struct ProtocolCodegen { let wrapperName = "Any\(proto.name)" let protocolName = proto.name - var methodDecls: [DeclSyntax] = [] + var methodDecls: [CodeFragmentPrinter] = [] var externDecls: [DeclSyntax] = [] for method in proto.methods { @@ -1523,72 +1585,72 @@ struct ProtocolCodegen { abiParameters: builder.abiParameterSignatures, returnType: builder.abiReturnType ) - let externFuncDecl = SwiftCodePattern.buildExternFunctionDecl( + let externDeclPrinter = CodeFragmentPrinter() + SwiftCodePattern.buildExternFunctionDecl( + printer: externDeclPrinter, moduleName: moduleName, abiName: method.abiName, functionName: "_extern_\(method.name)", signature: externSignature ) - externDecls.append(DeclSyntax(externFuncDecl)) - let methodImplementation = DeclSyntax( - FunctionDeclSyntax( - name: .identifier(method.name), - signature: signature, - body: builder.getBody() - ) - ) - - methodDecls.append(methodImplementation) + externDecls.append(DeclSyntax("\(raw: externDeclPrinter.lines.joined(separator: "\n"))")) + let methodImplPrinter = CodeFragmentPrinter() + methodImplPrinter.write("func \(method.name)\(signature) {") + methodImplPrinter.indent { + methodImplPrinter.write(lines: builder.body.lines) + } + methodImplPrinter.write("}") + methodDecls.append(methodImplPrinter) } - var propertyDecls: [DeclSyntax] = [] + var propertyDecls: [CodeFragmentPrinter] = [] for property in proto.properties { - let (propertyImpl, propertyExternDecls) = try renderProtocolProperty( + let propertyDeclPrinter = CodeFragmentPrinter() + let propertyExternDecls = try renderProtocolProperty( + printer: propertyDeclPrinter, property: property, protocolName: protocolName, moduleName: moduleName ) - propertyDecls.append(propertyImpl) + propertyDecls.append(propertyDeclPrinter) externDecls.append(contentsOf: propertyExternDecls) } - let structDecl = StructDeclSyntax( - name: .identifier(wrapperName), - inheritanceClause: InheritanceClauseSyntax( - inheritedTypesBuilder: { - InheritedTypeSyntax(type: IdentifierTypeSyntax(name: .identifier(protocolName))) - InheritedTypeSyntax(type: IdentifierTypeSyntax(name: .identifier("_BridgedSwiftProtocolWrapper"))) - } - ), - memberBlockBuilder: { - DeclSyntax( - """ - let jsObject: JSObject - """ - ).with(\.trailingTrivia, .newlines(2)) + let structDeclPrinter = CodeFragmentPrinter() + structDeclPrinter.write("struct \(wrapperName): \(protocolName), _BridgedSwiftProtocolWrapper {") + structDeclPrinter.indent { + structDeclPrinter.write("let jsObject: JSObject") + structDeclPrinter.nextLine() - for decl in methodDecls + propertyDecls { - decl.with(\.trailingTrivia, .newlines(2)) - } + for methodDecl in methodDecls { + structDeclPrinter.write(lines: methodDecl.lines) + structDeclPrinter.nextLine() + } - DeclSyntax( - """ + for decl in propertyDecls { + structDeclPrinter.write(lines: decl.lines) + structDeclPrinter.nextLine() + } + structDeclPrinter.write( + multilineString: """ static func bridgeJSLiftParameter(_ value: Int32) -> Self { - return \(raw: wrapperName)(jsObject: JSObject(id: UInt32(bitPattern: value))) + return \(wrapperName)(jsObject: JSObject(id: UInt32(bitPattern: value))) } """ - ) - } - ) - return [DeclSyntax(structDecl)] + externDecls + ) + } + structDeclPrinter.write("}") + + return ["\(raw: structDeclPrinter.lines.joined(separator: "\n"))"] + externDecls } private func renderProtocolProperty( + printer: CodeFragmentPrinter, property: ExportedProtocolProperty, protocolName: String, moduleName: String - ) throws -> (propertyDecl: DeclSyntax, externDecls: [DeclSyntax]) { + ) throws -> [DeclSyntax] { let getterAbiName = ABINameGenerator.generateABIName( baseName: property.name, operation: "get", @@ -1614,37 +1676,27 @@ struct ProtocolCodegen { abiParameters: getterBuilder.abiParameterSignatures, returnType: getterBuilder.abiReturnType ) - let getterExternDecl = SwiftCodePattern.buildExternFunctionDecl( + let getterExternDeclPrinter = CodeFragmentPrinter() + SwiftCodePattern.buildExternFunctionDecl( + printer: getterExternDeclPrinter, moduleName: moduleName, abiName: getterAbiName, functionName: getterAbiName, signature: getterExternSignature ) + let getterExternDecl = DeclSyntax("\(raw: getterExternDeclPrinter.lines.joined(separator: "\n"))") + var externDecls: [DeclSyntax] = [getterExternDecl] + + printer.write("var \(property.name): \(property.type.swiftType) {") + try printer.indent { + printer.write("get {") + printer.indent { + printer.write(lines: getterBuilder.body.lines) + } + printer.write("}") + + if property.isReadonly { return } - if property.isReadonly { - let propertyDecl = VariableDeclSyntax( - bindingSpecifier: .keyword(.var), - bindings: PatternBindingListSyntax { - PatternBindingSyntax( - pattern: IdentifierPatternSyntax(identifier: .identifier(property.name)), - typeAnnotation: TypeAnnotationSyntax( - type: IdentifierTypeSyntax(name: .identifier(property.type.swiftType)) - ), - accessorBlock: AccessorBlockSyntax( - accessors: .accessors( - AccessorDeclListSyntax { - AccessorDeclSyntax( - accessorSpecifier: .keyword(.get), - body: getterBuilder.getBody() - ) - } - ) - ) - ) - } - ) - return (DeclSyntax(propertyDecl), [DeclSyntax(getterExternDecl)]) - } else { let setterBuilder = ImportTS.CallJSEmission( moduleName: moduleName, abiName: setterAbiName, @@ -1659,40 +1711,26 @@ struct ProtocolCodegen { abiParameters: setterBuilder.abiParameterSignatures, returnType: setterBuilder.abiReturnType ) - let setterExternDecl = SwiftCodePattern.buildExternFunctionDecl( + let setterExternDeclPrinter = CodeFragmentPrinter() + SwiftCodePattern.buildExternFunctionDecl( + printer: setterExternDeclPrinter, moduleName: moduleName, abiName: setterAbiName, functionName: setterAbiName, signature: setterExternSignature ) + let setterExternDecl = DeclSyntax("\(raw: setterExternDeclPrinter.lines.joined(separator: "\n"))") + externDecls.append(setterExternDecl) - let propertyDecl = VariableDeclSyntax( - bindingSpecifier: .keyword(.var), - bindings: PatternBindingListSyntax { - PatternBindingSyntax( - pattern: IdentifierPatternSyntax(identifier: .identifier(property.name)), - typeAnnotation: TypeAnnotationSyntax( - type: IdentifierTypeSyntax(name: .identifier(property.type.swiftType)) - ), - accessorBlock: AccessorBlockSyntax( - accessors: .accessors( - AccessorDeclListSyntax { - AccessorDeclSyntax( - accessorSpecifier: .keyword(.get), - body: getterBuilder.getBody() - ) - AccessorDeclSyntax( - accessorSpecifier: .keyword(.set), - body: setterBuilder.getBody() - ) - } - ) - ) - ) - } - ) - return (DeclSyntax(propertyDecl), [DeclSyntax(getterExternDecl), DeclSyntax(setterExternDecl)]) + printer.write("set {") + printer.indent { + printer.write(lines: setterBuilder.body.lines) + } + printer.write("}") } + printer.write("}") + + return externDecls } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift index d5cc945ee..8eead20b7 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift @@ -85,16 +85,16 @@ public struct ImportTS { let moduleName: String let context: BridgeContext - var body: [CodeBlockItemSyntax] = [] - var abiParameterForwardings: [LabeledExprSyntax] = [] + var body = CodeFragmentPrinter() + var abiParameterForwardings: [String] = [] var abiParameterSignatures: [(name: String, type: WasmCoreType)] = [] var abiReturnType: WasmCoreType? // Track destructured variable names for multiple lowered parameters var destructuredVarNames: [String] = [] // Stack-lowered parameters should be evaluated in reverse order to match LIFO stacks - var stackLoweringStmts: [CodeBlockItemSyntax] = [] + var stackLoweringStmts: [String] = [] // Values to extend lifetime during call - var valuesToExtendLifetimeDuringCall: [ExprSyntax] = [] + var valuesToExtendLifetimeDuringCall: [String] = [] init(moduleName: String, abiName: String, context: BridgeContext = .importTS) { self.moduleName = moduleName @@ -108,34 +108,17 @@ public struct ImportTS { switch param.type { case .closure(let signature, useJSTypedClosure: false): let jsTypedClosureType = BridgeType.closure(signature, useJSTypedClosure: true).swiftType - body.append("let \(raw: param.name) = \(raw: jsTypedClosureType)(\(raw: param.name))") + body.write("let \(param.name) = \(jsTypedClosureType)(\(param.name))") // The just created JSObject is not owned by the caller unlike those passed in parameters, // so we need to extend its lifetime during the call to ensure the JSObject.id is valid. - valuesToExtendLifetimeDuringCall.append("\(raw: param.name)") + valuesToExtendLifetimeDuringCall.append(param.name) default: break } let initializerExpr = ExprSyntax("\(raw: param.name).bridgeJSLowerParameter()") if loweringInfo.loweredParameters.isEmpty { - let stmt = CodeBlockItemSyntax( - item: .decl( - DeclSyntax( - VariableDeclSyntax( - bindingSpecifier: .keyword(.let), - bindings: PatternBindingListSyntax { - PatternBindingSyntax( - pattern: PatternSyntax( - IdentifierPatternSyntax(identifier: .wildcardToken()) - ), - initializer: InitializerClauseSyntax(value: initializerExpr) - ) - } - ) - ) - ) - ) - stackLoweringStmts.insert(stmt, at: 0) + stackLoweringStmts.insert("let _ = \(initializerExpr)", at: 0) return } @@ -145,40 +128,14 @@ public struct ImportTS { } // Always add destructuring statement to body (unified for single and multiple) - let pattern: PatternSyntax + let pattern: String if destructuredNames.count == 1 { - pattern = PatternSyntax(IdentifierPatternSyntax(identifier: .identifier(destructuredNames[0]))) + pattern = destructuredNames[0] } else { - pattern = PatternSyntax( - TuplePatternSyntax { - for name in destructuredNames { - TuplePatternElementSyntax( - pattern: IdentifierPatternSyntax(identifier: .identifier(name)) - ) - } - } - ) + pattern = "(" + destructuredNames.joined(separator: ", ") + ")" } - body.append( - CodeBlockItemSyntax( - item: .decl( - DeclSyntax( - VariableDeclSyntax( - bindingSpecifier: .keyword(.let), - bindings: PatternBindingListSyntax { - PatternBindingSyntax( - pattern: pattern, - initializer: InitializerClauseSyntax( - value: initializerExpr - ) - ) - } - ) - ) - ) - ) - ) + body.write("let \(pattern) = \(initializerExpr)") destructuredVarNames.append(contentsOf: destructuredNames) // Add to signatures and forwardings (unified for both single and multiple) @@ -194,63 +151,36 @@ public struct ImportTS { // Always use destructured variable in call without labels // Swift allows omitting labels when they match parameter names - let callExpr = ExprSyntax("\(raw: destructuredNames[index])") - abiParameterForwardings.append( - LabeledExprSyntax(expression: callExpr) - ) + abiParameterForwardings.append(destructuredNames[index]) } } func call(returnType: BridgeType) throws { - let liftingInfo = try returnType.liftingReturnInfo(context: context) - body.append(contentsOf: stackLoweringStmts) - - var callExpr = FunctionCallExprSyntax( - calledExpression: ExprSyntax("\(raw: abiName)"), - leftParen: .leftParenToken(), - arguments: LabeledExprListSyntax { - for forwarding in abiParameterForwardings { - forwarding - } - }, - rightParen: .rightParenToken() - ) + let liftingInfo: BridgeType.LiftingReturnInfo = try returnType.liftingReturnInfo(context: context) + for stmt in stackLoweringStmts { + body.write(stmt.description) + } + + let assign = + (returnType == .void || returnType.usesSideChannelForOptionalReturn() || liftingInfo.valueToLift == nil) + ? "" : "let ret = " + let callExpr = "\(abiName)(\(abiParameterForwardings.joined(separator: ", ")))" if !valuesToExtendLifetimeDuringCall.isEmpty { - callExpr = FunctionCallExprSyntax( - calledExpression: ExprSyntax("withExtendedLifetime"), - leftParen: .leftParenToken(), - arguments: LabeledExprListSyntax { - LabeledExprSyntax( - expression: TupleExprSyntax( - elements: LabeledExprListSyntax { - for value in valuesToExtendLifetimeDuringCall { - LabeledExprSyntax(expression: value) - } - } - ) - ) - }, - rightParen: .rightParenToken(), - trailingClosure: ClosureExprSyntax( - leftBrace: .leftBraceToken(), - statements: CodeBlockItemListSyntax { - CodeBlockItemSyntax(item: .stmt(StmtSyntax(ExpressionStmtSyntax(expression: callExpr)))) - }, - rightBrace: .rightBraceToken() - ) + body.write( + "\(assign)withExtendedLifetime((\(valuesToExtendLifetimeDuringCall.joined(separator: ", ")))) {" ) - } - - if returnType == .void || returnType.usesSideChannelForOptionalReturn() || liftingInfo.valueToLift == nil { - body.append(CodeBlockItemSyntax(item: .stmt(StmtSyntax(ExpressionStmtSyntax(expression: callExpr))))) + body.indent { + body.write(callExpr) + } + body.write("}") } else { - body.append("let ret = \(raw: callExpr)") + body.write("\(assign)\(callExpr)") } // Add exception check for ImportTS context if context == .importTS { - body.append("if let error = _swift_js_take_exception() { throw error }") + body.write("if let error = _swift_js_take_exception() { throw error }") } } @@ -265,54 +195,30 @@ public struct ImportTS { if returnType.usesSideChannelForOptionalReturn() { // Side channel returns: extern function returns Void, value is retrieved via side channel abiReturnType = nil - body.append( - CodeBlockItemSyntax( - item: .stmt( - StmtSyntax( - ReturnStmtSyntax( - expression: ExprSyntax( - "\(raw: returnType.swiftType).bridgeJSLiftReturnFromSideChannel()" - ) - ) - ) - ) - ) - ) + body.write("return \(returnType.swiftType).bridgeJSLiftReturnFromSideChannel()") } else { abiReturnType = liftingInfo.valueToLift - let liftExpr: ExprSyntax + let liftExpr: String switch returnType { case .closure(let signature, _): - liftExpr = ExprSyntax("_BJS_Closure_\(raw: signature.mangleName).bridgeJSLift(ret)") + liftExpr = "_BJS_Closure_\(signature.mangleName).bridgeJSLift(ret)" default: if liftingInfo.valueToLift != nil { - liftExpr = "\(raw: returnType.swiftType).bridgeJSLiftReturn(ret)" + liftExpr = "\(returnType.swiftType).bridgeJSLiftReturn(ret)" } else { - liftExpr = "\(raw: returnType.swiftType).bridgeJSLiftReturn()" + liftExpr = "\(returnType.swiftType).bridgeJSLiftReturn()" } } - body.append( - CodeBlockItemSyntax( - item: .stmt( - StmtSyntax( - ReturnStmtSyntax(expression: liftExpr) - ) - ) - ) - ) + body.write("return \(liftExpr)") } } - func getBody() -> CodeBlockSyntax { - return CodeBlockSyntax(statements: CodeBlockItemListSyntax(body)) - } - func assignThis(returnType: BridgeType) { guard case .jsObject = returnType else { preconditionFailure("assignThis can only be called with a jsObject return type") } abiReturnType = .i32 - body.append("self.jsObject = JSObject(id: UInt32(bitPattern: ret))") + body.write("self.jsObject = JSObject(id: UInt32(bitPattern: ret))") } func renderImportDecl() -> DeclSyntax { @@ -321,40 +227,33 @@ public struct ImportTS { returnType: abiReturnType ) - // Build extern function declaration (no body) - let externFuncDecl = FunctionDeclSyntax( - attributes: SwiftCodePattern.buildExternAttribute(moduleName: moduleName, abiName: abiName), - modifiers: DeclModifierListSyntax { - DeclModifierSyntax(name: .keyword(.fileprivate)).with(\.trailingTrivia, .space) - }, - funcKeyword: .keyword(.func).with(\.trailingTrivia, .space), - name: .identifier(abiName), - signature: signature - ) - - // Build stub function declaration (with fatalError body) - let stubFuncDecl = FunctionDeclSyntax( - modifiers: DeclModifierListSyntax { - DeclModifierSyntax(name: .keyword(.fileprivate)).with(\.trailingTrivia, .space) + let printer = CodeFragmentPrinter() + SwiftCodePattern.buildWasmConditionalCompilationDecls( + printer: printer, + wasmDecl: { printer in + SwiftCodePattern.buildExternFunctionDecl( + printer: printer, + moduleName: moduleName, + abiName: abiName, + functionName: abiName, + signature: signature + ) }, - funcKeyword: .keyword(.func).with(\.trailingTrivia, .space), - name: .identifier(abiName), - signature: signature, - body: CodeBlockSyntax { - "fatalError(\"Only available on WebAssembly\")" + elseDecl: { printer in + printer.write( + multilineString: """ + fileprivate func \(abiName)\(signature) { + fatalError("Only available on WebAssembly") + } + """ + ) } ) - - // Use conditional compilation helper - return DeclSyntax( - SwiftCodePattern.buildWasmConditionalCompilationDecls( - wasmDecl: DeclSyntax(externFuncDecl), - elseDecl: DeclSyntax(stubFuncDecl) - ) - ) + return "\(raw: printer.lines.joined(separator: "\n"))" } func renderThunkDecl(name: String, parameters: [Parameter], returnType: BridgeType) -> DeclSyntax { + let printer = CodeFragmentPrinter() let effects = Effects(isAsync: false, isThrows: true) let signature = SwiftSignatureBuilder.buildFunctionSignature( parameters: parameters, @@ -362,35 +261,28 @@ public struct ImportTS { effects: effects, useWildcardLabels: true ) - return DeclSyntax( - FunctionDeclSyntax( - name: .identifier(name.backtickIfNeeded()), - signature: signature, - body: CodeBlockSyntax { - body - } - ) - ) + printer.write("func \(name.backtickIfNeeded())\(signature) {") + printer.indent { + printer.write(lines: body.lines) + } + printer.write("}") + return "\(raw: printer.lines.joined(separator: "\n"))" } func renderConstructorDecl(parameters: [Parameter]) -> DeclSyntax { + let printer = CodeFragmentPrinter() let effects = Effects(isAsync: false, isThrows: true) - // Constructors don't have return types, so build signature without return clause - let signature = FunctionSignatureSyntax( - parameterClause: SwiftSignatureBuilder.buildParameterClause( - parameters: parameters, - useWildcardLabels: true - ), - effectSpecifiers: SwiftSignatureBuilder.buildEffectSpecifiers(effects: effects) - ) - return DeclSyntax( - InitializerDeclSyntax( - signature: signature, - bodyBuilder: { - body - } - ) + let parameterClause = SwiftSignatureBuilder.buildParameterClause( + parameters: parameters, + useWildcardLabels: true ) + let effectSpecifiers = SwiftSignatureBuilder.buildEffectSpecifiers(effects: effects) + printer.write("init\(parameterClause)\(effectSpecifiers.map { " \($0)" } ?? "") {") + printer.indent { + printer.write(lines: body.lines) + } + printer.write("}") + return "\(raw: printer.lines.joined(separator: "\n"))" } } @@ -600,12 +492,17 @@ struct SwiftSignatureBuilder { returnType: BridgeType, effects: Effects? = nil, useWildcardLabels: Bool = false - ) -> FunctionSignatureSyntax { - return FunctionSignatureSyntax( - parameterClause: buildParameterClause(parameters: parameters, useWildcardLabels: useWildcardLabels), - effectSpecifiers: effects.flatMap { buildEffectSpecifiers(effects: $0) }, - returnClause: buildReturnClause(returnType: returnType) - ) + ) -> String { + let parameterClause = buildParameterClause(parameters: parameters, useWildcardLabels: useWildcardLabels) + let effectSpecifiers = effects.flatMap { buildEffectSpecifiers(effects: $0) } + let returnClause = buildReturnClause(returnType: returnType) + var out = "" + out += parameterClause + if let effectSpecifiers { + out += " \(effectSpecifiers)" + } + out += returnClause + return out } /// Builds a function signature for ABI/extern functions using WasmCoreType parameters @@ -619,12 +516,14 @@ struct SwiftSignatureBuilder { abiParameters: [(name: String, type: WasmCoreType)], returnType: WasmCoreType?, effects: Effects? = nil - ) -> FunctionSignatureSyntax { - return FunctionSignatureSyntax( - parameterClause: buildABIParameterClause(abiParameters: abiParameters), - effectSpecifiers: effects.flatMap { buildEffectSpecifiers(effects: $0) }, - returnClause: buildABIReturnClause(returnType: returnType) - ) + ) -> String { + var out = "" + out += buildABIParameterClause(abiParameters: abiParameters) + if let effects = effects, let effectSpecifiers = buildEffectSpecifiers(effects: effects) { + out += " \(effectSpecifiers)" + } + out += buildABIReturnClause(returnType: returnType) + return out } /// Builds a parameter clause from an array of Parameter structs @@ -639,48 +538,28 @@ struct SwiftSignatureBuilder { static func buildParameterClause( parameters: [Parameter], useWildcardLabels: Bool = false - ) -> FunctionParameterClauseSyntax { - return FunctionParameterClauseSyntax(parametersBuilder: { - for param in parameters { - let paramTypeSyntax = buildParameterTypeSyntax(from: param.type) - if useWildcardLabels { - // Always use wildcard labels: "_ name: Type" - FunctionParameterSyntax( - firstName: .wildcardToken(), - secondName: .identifier(param.name), - colon: .colonToken(), - type: paramTypeSyntax - ) - } else { - let label = param.label ?? param.name - if label == param.name { - // External label same as parameter name: "count: Int" - FunctionParameterSyntax( - firstName: .identifier(label), - secondName: nil, - colon: .colonToken(), - type: paramTypeSyntax - ) - } else if param.label == nil { - // No label specified: use wildcard "_ name: Type" - FunctionParameterSyntax( - firstName: .wildcardToken(), - secondName: .identifier(param.name), - colon: .colonToken(), - type: paramTypeSyntax - ) - } else { - // External label differs: "label count: Int" - FunctionParameterSyntax( - firstName: .identifier(label), - secondName: .identifier(param.name), - colon: .colonToken(), - type: paramTypeSyntax - ) - } - } + ) -> String { + var out = "(" + out += parameters.map { param in + let label = param.label ?? param.name + let paramType = buildParameterTypeSyntax(from: param.type) + + if useWildcardLabels { + // Always use wildcard labels: "_ name: Type" + return "_ \(param.name): \(paramType)" + } else if label == param.name { + // External label same as parameter name: "count: Int" + return "\(param.name): \(paramType)" + } else if param.label == nil { + // No label specified: use wildcard "_ name: Type" + return "_ \(param.name): \(paramType)" + } else { + // External label differs: "label count: Int" + return "\(label) \(param.name): \(paramType)" } - }) + }.joined(separator: ", ") + out += ")" + return out } /// Builds a parameter clause for ABI/extern functions @@ -688,77 +567,56 @@ struct SwiftSignatureBuilder { /// All parameters use wildcard labels: "_ name: Type" static func buildABIParameterClause( abiParameters: [(name: String, type: WasmCoreType)] - ) -> FunctionParameterClauseSyntax { - return FunctionParameterClauseSyntax(parametersBuilder: { - for param in abiParameters { - FunctionParameterSyntax( - firstName: .wildcardToken().with(\.trailingTrivia, .space), - secondName: .identifier(param.name), - type: IdentifierTypeSyntax(name: .identifier(param.type.swiftType)) - ) - } - }) + ) -> String { + "(" + + abiParameters.map { param in + "_ \(param.name): \(param.type.swiftType)" + }.joined(separator: ", ") + ")" } /// Builds a return clause from a BridgeType /// /// Always returns a ReturnClauseSyntax, including for Void types /// (to match original behavior that explicitly includes "-> Void") - static func buildReturnClause(returnType: BridgeType) -> ReturnClauseSyntax? { - return ReturnClauseSyntax( - arrow: .arrowToken(), - type: buildTypeSyntax(from: returnType) - ) + static func buildReturnClause(returnType: BridgeType) -> String { + return " -> \(returnType.swiftType)" } /// Builds a return clause for ABI/extern functions /// /// Returns nil for Void (when returnType is nil), otherwise returns a ReturnClauseSyntax - static func buildABIReturnClause(returnType: WasmCoreType?) -> ReturnClauseSyntax? { + static func buildABIReturnClause(returnType: WasmCoreType?) -> String { guard let returnType = returnType else { - return ReturnClauseSyntax( - arrow: .arrowToken(), - type: IdentifierTypeSyntax(name: .identifier("Void")) - ) + return " -> Void" } - return ReturnClauseSyntax( - arrow: .arrowToken(), - type: IdentifierTypeSyntax(name: .identifier(returnType.swiftType)) - ) + return " -> \(returnType.swiftType)" } /// Builds effect specifiers (async/throws) from an Effects struct /// /// Uses JSException as the thrown error type for throws clauses - static func buildEffectSpecifiers(effects: Effects) -> FunctionEffectSpecifiersSyntax? { + static func buildEffectSpecifiers(effects: Effects) -> String? { guard effects.isAsync || effects.isThrows else { return nil } - return FunctionEffectSpecifiersSyntax( - asyncSpecifier: effects.isAsync ? .keyword(.async) : nil, - throwsClause: effects.isThrows - ? ThrowsClauseSyntax( - throwsSpecifier: .keyword(.throws), - leftParen: .leftParenToken(), - type: IdentifierTypeSyntax(name: .identifier("JSException")), - rightParen: .rightParenToken() - ) : nil - ) + var items: [String] = [] + if effects.isAsync { items.append("async") } + if effects.isThrows { items.append("throws(JSException)") } + return items.joined(separator: " ") } /// Builds a TypeSyntax node from a BridgeType /// /// Converts BridgeType to its Swift type representation as a TypeSyntax node - static func buildTypeSyntax(from type: BridgeType) -> TypeSyntax { - let identifierType = IdentifierTypeSyntax(name: .identifier(type.swiftType)) - return TypeSyntax(identifierType) + static func buildTypeSyntax(from type: BridgeType) -> String { + return type.swiftType } /// Builds a parameter type syntax from a BridgeType. - static func buildParameterTypeSyntax(from type: BridgeType) -> TypeSyntax { + static func buildParameterTypeSyntax(from type: BridgeType) -> String { switch type { case .closure(_, useJSTypedClosure: false): - return TypeSyntax("@escaping \(raw: type.swiftType)") + return "@escaping \(type.swiftType)" default: return buildTypeSyntax(from: type) } @@ -768,167 +626,69 @@ struct SwiftSignatureBuilder { enum SwiftCodePattern { /// Builds a conditional compilation block with #if arch(wasm32) and #else fatalError static func buildWasmConditionalCompilation( - wasmBody: CodeBlockItemListSyntax - ) -> IfConfigDeclSyntax { - return IfConfigDeclSyntax( - clauses: IfConfigClauseListSyntax { - IfConfigClauseSyntax( - poundKeyword: .poundIfToken(), - condition: ExprSyntax("arch(wasm32)"), - elements: .statements(wasmBody) - ) - IfConfigClauseSyntax( - poundKeyword: .poundElseToken(), - elements: .statements( - CodeBlockItemListSyntax { - "fatalError(\"Only available on WebAssembly\")" - } - ) - ) - } - ) + printer: CodeFragmentPrinter, + wasmBody: (_ printer: CodeFragmentPrinter) -> Void + ) { + printer.write("#if arch(wasm32)") + wasmBody(printer) + printer.write("#else") + printer.write("fatalError(\"Only available on WebAssembly\")") + printer.write("#endif") } /// Builds a conditional compilation block with #if arch(wasm32) and #else for declarations static func buildWasmConditionalCompilationDecls( - wasmDecl: DeclSyntax, - elseDecl: DeclSyntax - ) -> IfConfigDeclSyntax { - return IfConfigDeclSyntax( - clauses: IfConfigClauseListSyntax { - IfConfigClauseSyntax( - poundKeyword: .poundIfToken(), - condition: ExprSyntax("arch(wasm32)"), - elements: .statements( - CodeBlockItemListSyntax { - CodeBlockItemSyntax(item: .decl(wasmDecl)) - } - ) - ) - IfConfigClauseSyntax( - poundKeyword: .poundElseToken(), - elements: .statements( - CodeBlockItemListSyntax { - CodeBlockItemSyntax(item: .decl(elseDecl)) - } - ) - ) - } - ) + printer: CodeFragmentPrinter, + wasmDecl: (_ printer: CodeFragmentPrinter) -> Void, + elseDecl: (_ printer: CodeFragmentPrinter) -> Void + ) { + printer.write("#if arch(wasm32)") + wasmDecl(printer) + printer.write("#else") + elseDecl(printer) + printer.write("#endif") } /// Builds the @_extern attribute for WebAssembly extern function declarations /// Builds an @_extern function declaration (no body, just the declaration) static func buildExternFunctionDecl( + printer: CodeFragmentPrinter, moduleName: String, abiName: String, functionName: String, - signature: FunctionSignatureSyntax - ) -> FunctionDeclSyntax { - return FunctionDeclSyntax( - attributes: buildExternAttribute(moduleName: moduleName, abiName: abiName), - modifiers: DeclModifierListSyntax { - DeclModifierSyntax(name: .keyword(.fileprivate)) - }, - funcKeyword: .keyword(.func), - name: .identifier(functionName), - signature: signature - ) + signature: String + ) { + printer.write(buildExternAttribute(moduleName: moduleName, abiName: abiName)) + printer.write("fileprivate func \(functionName)\(signature)") } /// Builds the standard @_expose and @_cdecl attributes for WebAssembly-exposed functions - static func buildExposeAttributes(abiName: String) -> AttributeListSyntax { - return AttributeListSyntax { - #if canImport(SwiftSyntax602) - let exposeAttrArgs = AttributeSyntax.Arguments.argumentList( - LabeledExprListSyntax { - LabeledExprSyntax(label: nil, expression: DeclReferenceExprSyntax(baseName: "wasm")) - .with(\.trailingComma, .commaToken()) - LabeledExprSyntax(label: nil, expression: StringLiteralExprSyntax(content: abiName)) - } - ) - let cdeclAttrArgs = AttributeSyntax.Arguments.argumentList( - [ - LabeledExprSyntax(label: nil, expression: StringLiteralExprSyntax(content: abiName)) - ] - ) - #else - let exposeAttrArgs = AttributeSyntax.Arguments.exposeAttributeArguments( - ExposeAttributeArgumentsSyntax( - language: .identifier("wasm"), - comma: .commaToken(), - cxxName: StringLiteralExprSyntax(content: abiName) - ) - ) - let cdeclAttrArgs = AttributeSyntax.Arguments.string(StringLiteralExprSyntax(content: abiName)) - #endif - AttributeSyntax( - attributeName: IdentifierTypeSyntax(name: .identifier("_expose")), - leftParen: .leftParenToken(), - arguments: exposeAttrArgs, - rightParen: .rightParenToken() - ) - .with(\.trailingTrivia, .newline) - - AttributeSyntax( - attributeName: IdentifierTypeSyntax(name: .identifier("_cdecl")), - leftParen: .leftParenToken(), - arguments: cdeclAttrArgs, - rightParen: .rightParenToken() - ) - .with(\.trailingTrivia, .newline) - } + static func buildExposeAttributes(abiName: String) -> String { + return """ + @_expose(wasm, "\(abiName)") + @_cdecl("\(abiName)") + """ } /// Builds a function declaration with @_expose/@_cdecl attributes and conditional compilation static func buildExposedFunctionDecl( abiName: String, - signature: FunctionSignatureSyntax, - body: CodeBlockItemListSyntax - ) -> FunctionDeclSyntax { - let funcBody = CodeBlockSyntax { - buildWasmConditionalCompilation(wasmBody: body) + signature: String, + body: (CodeFragmentPrinter) -> Void + ) -> DeclSyntax { + let printer = CodeFragmentPrinter() + printer.write(buildExposeAttributes(abiName: abiName)) + printer.write("public func _\(abiName)\(signature) {") + printer.indent { + buildWasmConditionalCompilation(printer: printer, wasmBody: body) } - - return FunctionDeclSyntax( - attributes: buildExposeAttributes(abiName: abiName), - modifiers: DeclModifierListSyntax { - DeclModifierSyntax(name: .keyword(.public)) - }, - funcKeyword: .keyword(.func), - name: .identifier("_\(abiName)"), - signature: signature, - body: funcBody - ) + printer.write("}") + return "\(raw: printer.lines.joined(separator: "\n"))" } /// Builds the @_extern attribute for WebAssembly extern function declarations - static func buildExternAttribute(moduleName: String, abiName: String) -> AttributeListSyntax { - return AttributeListSyntax { - AttributeSyntax( - attributeName: IdentifierTypeSyntax(name: .identifier("_extern")), - leftParen: .leftParenToken(), - arguments: .argumentList( - LabeledExprListSyntax { - LabeledExprSyntax( - expression: ExprSyntax("wasm") - ) - LabeledExprSyntax( - label: .identifier("module"), - colon: .colonToken(), - expression: StringLiteralExprSyntax(content: moduleName) - ) - LabeledExprSyntax( - label: .identifier("name"), - colon: .colonToken(), - expression: StringLiteralExprSyntax(content: abiName) - ) - } - ), - rightParen: .rightParenToken() - ) - .with(\.trailingTrivia, .newline) - } + static func buildExternAttribute(moduleName: String, abiName: String) -> String { + return "@_extern(wasm, module: \"\(moduleName)\", name: \"\(abiName)\")" } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift b/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift index ed6fa04f0..68c07f225 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift @@ -60,6 +60,12 @@ public final class CodeFragmentPrinter { self.write(lines: printer.lines) } + public func write(multilineString: String) { + for line in multilineString.split(separator: "\n") { + write(line) + } + } + public func indent() { indentLevel += 1 } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift index 023caf21f..261c0b066 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift @@ -229,17 +229,19 @@ public func _bjs_processOptionalIntArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Optional.bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -254,17 +256,19 @@ public func _bjs_processOptionalStringArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Optional.bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -281,10 +285,11 @@ public func _bjs_processOptionalArray(_ values: Int32) -> Void { } else { return [Int].bridgeJSLiftParameter() } - }()) + }()) let __bjs_isSome_ret = ret != nil if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn()} + __bjs_unwrapped_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) #else fatalError("Only available on WebAssembly") @@ -299,17 +304,19 @@ public func _bjs_processOptionalPointArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Optional.bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.bridgeJSLowerReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -324,17 +331,19 @@ public func _bjs_processOptionalDirectionArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Optional.bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -349,17 +358,19 @@ public func _bjs_processOptionalStatusArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Optional.bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -374,14 +385,15 @@ public func _bjs_processNestedIntArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [[Int]] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append([Int].bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn()} + __bjs_elem_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -396,14 +408,15 @@ public func _bjs_processNestedStringArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [[String]] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append([String].bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn()} + __bjs_elem_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -418,14 +431,15 @@ public func _bjs_processNestedPointArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [[Point]] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append([Point].bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn()} + __bjs_elem_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -451,14 +465,15 @@ public func _bjs_processNestedItemArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [[Item]] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append([Item].bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn()} + __bjs_elem_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -484,17 +499,19 @@ public func _bjs_processOptionalJSObjectArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Optional.bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -509,14 +526,15 @@ public func _bjs_processNestedJSObjectArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [[JSObject]] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append([JSObject].bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn()} + __bjs_elem_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.swift index 4c97553de..f5230f213 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.swift @@ -4,7 +4,7 @@ public func _bjs_asyncReturnVoid() -> Int32 { #if arch(wasm32) let ret = JSPromise.async { await asyncReturnVoid() - } .jsObject + }.jsObject return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -17,7 +17,7 @@ public func _bjs_asyncRoundTripInt(_ v: Int32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { return await asyncRoundTripInt(_: Int.bridgeJSLiftParameter(v)).jsValue - } .jsObject + }.jsObject return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -30,7 +30,7 @@ public func _bjs_asyncRoundTripString(_ vBytes: Int32, _ vLength: Int32) -> Int3 #if arch(wasm32) let ret = JSPromise.async { return await asyncRoundTripString(_: String.bridgeJSLiftParameter(vBytes, vLength)).jsValue - } .jsObject + }.jsObject return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -43,7 +43,7 @@ public func _bjs_asyncRoundTripBool(_ v: Int32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { return await asyncRoundTripBool(_: Bool.bridgeJSLiftParameter(v)).jsValue - } .jsObject + }.jsObject return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -56,7 +56,7 @@ public func _bjs_asyncRoundTripFloat(_ v: Float32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { return await asyncRoundTripFloat(_: Float.bridgeJSLiftParameter(v)).jsValue - } .jsObject + }.jsObject return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -69,7 +69,7 @@ public func _bjs_asyncRoundTripDouble(_ v: Float64) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { return await asyncRoundTripDouble(_: Double.bridgeJSLiftParameter(v)).jsValue - } .jsObject + }.jsObject return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -82,7 +82,7 @@ public func _bjs_asyncRoundTripJSObject(_ v: Int32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { return await asyncRoundTripJSObject(_: JSObject.bridgeJSLiftParameter(v)).jsValue - } .jsObject + }.jsObject return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift index 26454a2a7..f2029749c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift @@ -309,36 +309,36 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { case .success(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(0) case .failure(let param0, let param1): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) let __bjs_isSome_param1 = param1 != nil if let __bjs_unwrapped_param1 = param1 { - __bjs_unwrapped_param1.bridgeJSLowerStackReturn() + __bjs_unwrapped_param1.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) return Int32(1) case .status(let param0, let param1, let param2): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) let __bjs_isSome_param1 = param1 != nil if let __bjs_unwrapped_param1 = param1 { - __bjs_unwrapped_param1.bridgeJSLowerStackReturn() + __bjs_unwrapped_param1.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) let __bjs_isSome_param2 = param2 != nil if let __bjs_unwrapped_param2 = param2 { - __bjs_unwrapped_param2.bridgeJSLowerStackReturn() + __bjs_unwrapped_param2.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param2 ? 1 : 0) return Int32(2) @@ -360,36 +360,36 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { case .success(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(0)) case .failure(let param0, let param1): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) let __bjs_isSome_param1 = param1 != nil if let __bjs_unwrapped_param1 = param1 { - __bjs_unwrapped_param1.bridgeJSLowerStackReturn() + __bjs_unwrapped_param1.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) _swift_js_push_tag(Int32(1)) case .status(let param0, let param1, let param2): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) let __bjs_isSome_param1 = param1 != nil if let __bjs_unwrapped_param1 = param1 { - __bjs_unwrapped_param1.bridgeJSLowerStackReturn() + __bjs_unwrapped_param1.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) let __bjs_isSome_param2 = param2 != nil if let __bjs_unwrapped_param2 = param2 { - __bjs_unwrapped_param2.bridgeJSLowerStackReturn() + __bjs_unwrapped_param2.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param2 ? 1 : 0) _swift_js_push_tag(Int32(2)) @@ -474,14 +474,14 @@ extension TypedPayloadResult: _BridgedSwiftAssociatedValueEnum { case .optPrecision(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(2) case .optDirection(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(3) @@ -511,14 +511,14 @@ extension TypedPayloadResult: _BridgedSwiftAssociatedValueEnum { case .optPrecision(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(2)) case .optDirection(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(3)) @@ -618,13 +618,13 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { return .optNestedEnum(Optional.bridgeJSLiftParameter()) case 4: return .optArray({ - let __isSome = _swift_js_pop_i32() - if __isSome == 0 { - return Optional<[Int]>.none - } else { - return [Int].bridgeJSLiftParameter() - } - }()) + let __isSome = _swift_js_pop_i32() + if __isSome == 0 { + return Optional<[Int]>.none + } else { + return [Int].bridgeJSLiftParameter() + } +}()) case 5: return .empty default: @@ -639,35 +639,35 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { case .optStruct(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerReturn() + __bjs_unwrapped_param0.bridgeJSLowerReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(0) case .optClass(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(1) case .optJSObject(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(2) case .optNestedEnum(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - _swift_js_push_i32(__bjs_unwrapped_param0.bridgeJSLowerParameter()) + _swift_js_push_i32(__bjs_unwrapped_param0.bridgeJSLowerParameter()) } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(3) case .optArray(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerReturn() + __bjs_unwrapped_param0.bridgeJSLowerReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(4) @@ -691,35 +691,35 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { case .optStruct(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerReturn() + __bjs_unwrapped_param0.bridgeJSLowerReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(0)) case .optClass(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(1)) case .optJSObject(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(2)) case .optNestedEnum(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - _swift_js_push_i32(__bjs_unwrapped_param0.bridgeJSLowerParameter()) + _swift_js_push_i32(__bjs_unwrapped_param0.bridgeJSLowerParameter()) } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(3)) case .optArray(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerReturn() + __bjs_unwrapped_param0.bridgeJSLowerReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(4)) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift index 6d9bee080..cd0f56694 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift @@ -1,8 +1,6 @@ extension FooContainer: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> FooContainer { - let optionalFoo = Optional.bridgeJSLiftParameter().map { - Foo(unsafelyWrapping: $0) - } + let optionalFoo = Optional.bridgeJSLiftParameter().map { Foo(unsafelyWrapping: $0) } let foo = Foo(unsafelyWrapping: JSObject.bridgeJSLiftParameter()) return FooContainer(foo: foo, optionalFoo: optionalFoo) } @@ -11,7 +9,7 @@ extension FooContainer: _BridgedSwiftStruct { self.foo.jsObject.bridgeJSLowerStackReturn() let __bjs_isSome_optionalFoo = self.optionalFoo != nil if let __bjs_unwrapped_optionalFoo = self.optionalFoo { - __bjs_unwrapped_optionalFoo.jsObject.bridgeJSLowerStackReturn() + __bjs_unwrapped_optionalFoo.jsObject.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_optionalFoo ? 1 : 0) } @@ -82,15 +80,13 @@ public func _bjs_processFooArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [Foo] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Foo(unsafelyWrapping: JSObject.bridgeJSLiftParameter())) } __result.reverse() return __result - }()) - ret.map { - $0.jsObject - } .bridgeJSLowerReturn() + }()) + ret.map { $0.jsObject }.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -104,19 +100,19 @@ public func _bjs_processOptionalFooArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { - __result.append(Optional.bridgeJSLiftParameter().map { - Foo(unsafelyWrapping: $0) - }) + for _ in 0..<__count { + __result.append(Optional.bridgeJSLiftParameter().map { Foo(unsafelyWrapping: $0) }) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.jsObject.bridgeJSLowerStackReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.jsObject.bridgeJSLowerStackReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.swift index f3550129c..b4e45bbc9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.swift @@ -41,10 +41,11 @@ public func _bjs_roundTripOptionalJSValueArray(_ values: Int32) -> Void { } else { return [JSValue].bridgeJSLiftParameter() } - }()) + }()) let __bjs_isSome_ret = ret != nil if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn()} + __bjs_unwrapped_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) #else fatalError("Only available on WebAssembly") diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift index 3536b53cb..55521dbaf 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift @@ -417,9 +417,7 @@ extension Priority: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { public func _bjs_processDelegates() -> Void { #if arch(wasm32) let ret = processDelegates(_: [AnyMyViewControllerDelegate].bridgeJSLiftParameter()) - ret.map { - $0 as! AnyMyViewControllerDelegate - } .bridgeJSLowerReturn() + ret.map { $0 as! AnyMyViewControllerDelegate }.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -590,9 +588,7 @@ public func _bjs_MyViewController_delegate_set(_ _self: UnsafeMutableRawPointer, @_cdecl("bjs_MyViewController_secondDelegate_get") public func _bjs_MyViewController_secondDelegate_get(_ _self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let ret = MyViewController.bridgeJSLiftParameter(_self).secondDelegate.flatMap { - $0 as? AnyMyViewControllerDelegate - } + let ret = MyViewController.bridgeJSLiftParameter(_self).secondDelegate.flatMap { $0 as? AnyMyViewControllerDelegate } return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -660,9 +656,7 @@ public func _bjs_DelegateManager_notifyAll(_ _self: UnsafeMutableRawPointer) -> public func _bjs_DelegateManager_delegates_get(_ _self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) let ret = DelegateManager.bridgeJSLiftParameter(_self).delegates - ret.map { - $0 as! AnyMyViewControllerDelegate - } .bridgeJSLowerReturn() + ret.map { $0 as! AnyMyViewControllerDelegate }.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.swift index ca2467249..1ff0a4ce8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.swift @@ -17,12 +17,12 @@ extension DataPoint: _BridgedSwiftStruct { self.label.bridgeJSLowerStackReturn() let __bjs_isSome_optCount = self.optCount != nil if let __bjs_unwrapped_optCount = self.optCount { - __bjs_unwrapped_optCount.bridgeJSLowerStackReturn() + __bjs_unwrapped_optCount.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_optCount ? 1 : 0) let __bjs_isSome_optFlag = self.optFlag != nil if let __bjs_unwrapped_optFlag = self.optFlag { - __bjs_unwrapped_optFlag.bridgeJSLowerStackReturn() + __bjs_unwrapped_optFlag.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_optFlag ? 1 : 0) } @@ -84,7 +84,7 @@ extension Address: _BridgedSwiftStruct { self.city.bridgeJSLowerStackReturn() let __bjs_isSome_zipCode = self.zipCode != nil if let __bjs_unwrapped_zipCode = self.zipCode { - __bjs_unwrapped_zipCode.bridgeJSLowerStackReturn() + __bjs_unwrapped_zipCode.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_zipCode ? 1 : 0) } @@ -137,7 +137,7 @@ extension Person: _BridgedSwiftStruct { self.address.bridgeJSLowerReturn() let __bjs_isSome_email = self.email != nil if let __bjs_unwrapped_email = self.email { - __bjs_unwrapped_email.bridgeJSLowerStackReturn() + __bjs_unwrapped_email.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_email ? 1 : 0) } @@ -233,7 +233,7 @@ extension Measurement: _BridgedSwiftStruct { self.precision.bridgeJSLowerStackReturn() let __bjs_isSome_optionalPrecision = self.optionalPrecision != nil if let __bjs_unwrapped_optionalPrecision = self.optionalPrecision { - __bjs_unwrapped_optionalPrecision.bridgeJSLowerStackReturn() + __bjs_unwrapped_optionalPrecision.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_optionalPrecision ? 1 : 0) } @@ -277,7 +277,6 @@ extension ConfigStruct: _BridgedSwiftStruct { } @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - } init(unsafelyCopying jsObject: JSObject) { @@ -399,7 +398,7 @@ extension Container: _BridgedSwiftStruct { self.object.bridgeJSLowerStackReturn() let __bjs_isSome_optionalObject = self.optionalObject != nil if let __bjs_unwrapped_optionalObject = self.optionalObject { - __bjs_unwrapped_optionalObject.bridgeJSLowerStackReturn() + __bjs_unwrapped_optionalObject.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_optionalObject ? 1 : 0) } diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index b10a82fdf..af9f15dbc 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -655,7 +655,7 @@ fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsS private enum _BJS_Closure_20BridgeJSRuntimeTestsSiSSSd_SS { static func bridgeJSLift(_ callbackId: Int32) -> (Int, String, Double) -> String { let callback = JSObject.bridgeJSLiftParameter(callbackId) - return { [callback] param0, param1, param2 in + return { [callback] (param0, param1, param2) in #if arch(wasm32) let callbackValue = callback.bridgeJSLowerParameter() let param0Value = param0.bridgeJSLowerParameter() @@ -714,7 +714,7 @@ fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsS private enum _BJS_Closure_20BridgeJSRuntimeTestsSiSiSi_Si { static func bridgeJSLift(_ callbackId: Int32) -> (Int, Int, Int) -> Int { let callback = JSObject.bridgeJSLiftParameter(callbackId) - return { [callback] param0, param1, param2 in + return { [callback] (param0, param1, param2) in #if arch(wasm32) let callbackValue = callback.bridgeJSLowerParameter() let param0Value = param0.bridgeJSLowerParameter() @@ -773,7 +773,7 @@ fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsS private enum _BJS_Closure_20BridgeJSRuntimeTestsSiSi_Si { static func bridgeJSLift(_ callbackId: Int32) -> (Int, Int) -> Int { let callback = JSObject.bridgeJSLiftParameter(callbackId) - return { [callback] param0, param1 in + return { [callback] (param0, param1) in #if arch(wasm32) let callbackValue = callback.bridgeJSLowerParameter() let param0Value = param0.bridgeJSLowerParameter() @@ -2443,14 +2443,14 @@ extension TypedPayloadResult: _BridgedSwiftAssociatedValueEnum { case .optPrecision(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(2) case .optDirection(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(3) @@ -2480,14 +2480,14 @@ extension TypedPayloadResult: _BridgedSwiftAssociatedValueEnum { case .optPrecision(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(2)) case .optDirection(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(3)) @@ -2815,17 +2815,15 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { return .optNestedEnum(Optional.bridgeJSLiftParameter()) case 4: return .optArray({ - let __isSome = _swift_js_pop_i32() - if __isSome == 0 { - return Optional<[Int]>.none - } else { - return [Int].bridgeJSLiftParameter() - } - }()) + let __isSome = _swift_js_pop_i32() + if __isSome == 0 { + return Optional<[Int]>.none + } else { + return [Int].bridgeJSLiftParameter() + } +}()) case 5: - return .optJsClass(Optional.bridgeJSLiftParameter().map { - Foo(unsafelyWrapping: $0) - }) + return .optJsClass(Optional.bridgeJSLiftParameter().map { Foo(unsafelyWrapping: $0) }) case 6: return .empty default: @@ -2840,42 +2838,42 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { case .optStruct(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerReturn() + __bjs_unwrapped_param0.bridgeJSLowerReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(0) case .optClass(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(1) case .optJSObject(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(2) case .optNestedEnum(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - _swift_js_push_i32(__bjs_unwrapped_param0.bridgeJSLowerParameter()) + _swift_js_push_i32(__bjs_unwrapped_param0.bridgeJSLowerParameter()) } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(3) case .optArray(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerReturn() + __bjs_unwrapped_param0.bridgeJSLowerReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(4) case .optJsClass(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.jsObject.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.jsObject.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(5) @@ -2899,42 +2897,42 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { case .optStruct(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerReturn() + __bjs_unwrapped_param0.bridgeJSLowerReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(0)) case .optClass(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(1)) case .optJSObject(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(2)) case .optNestedEnum(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - _swift_js_push_i32(__bjs_unwrapped_param0.bridgeJSLowerParameter()) + _swift_js_push_i32(__bjs_unwrapped_param0.bridgeJSLowerParameter()) } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(3)) case .optArray(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerReturn() + __bjs_unwrapped_param0.bridgeJSLowerReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(4)) case .optJsClass(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.jsObject.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.jsObject.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(5)) @@ -2965,36 +2963,36 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { case .success(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(0) case .failure(let param0, let param1): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) let __bjs_isSome_param1 = param1 != nil if let __bjs_unwrapped_param1 = param1 { - __bjs_unwrapped_param1.bridgeJSLowerStackReturn() + __bjs_unwrapped_param1.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) return Int32(1) case .status(let param0, let param1, let param2): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) let __bjs_isSome_param1 = param1 != nil if let __bjs_unwrapped_param1 = param1 { - __bjs_unwrapped_param1.bridgeJSLowerStackReturn() + __bjs_unwrapped_param1.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) let __bjs_isSome_param2 = param2 != nil if let __bjs_unwrapped_param2 = param2 { - __bjs_unwrapped_param2.bridgeJSLowerStackReturn() + __bjs_unwrapped_param2.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param2 ? 1 : 0) return Int32(2) @@ -3016,36 +3014,36 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { case .success(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(0)) case .failure(let param0, let param1): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) let __bjs_isSome_param1 = param1 != nil if let __bjs_unwrapped_param1 = param1 { - __bjs_unwrapped_param1.bridgeJSLowerStackReturn() + __bjs_unwrapped_param1.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) _swift_js_push_tag(Int32(1)) case .status(let param0, let param1, let param2): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) let __bjs_isSome_param1 = param1 != nil if let __bjs_unwrapped_param1 = param1 { - __bjs_unwrapped_param1.bridgeJSLowerStackReturn() + __bjs_unwrapped_param1.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) let __bjs_isSome_param2 = param2 != nil if let __bjs_unwrapped_param2 = param2 { - __bjs_unwrapped_param2.bridgeJSLowerStackReturn() + __bjs_unwrapped_param2.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param2 ? 1 : 0) _swift_js_push_tag(Int32(2)) @@ -3176,12 +3174,12 @@ extension DataPoint: _BridgedSwiftStruct { self.label.bridgeJSLowerStackReturn() let __bjs_isSome_optCount = self.optCount != nil if let __bjs_unwrapped_optCount = self.optCount { - __bjs_unwrapped_optCount.bridgeJSLowerStackReturn() + __bjs_unwrapped_optCount.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_optCount ? 1 : 0) let __bjs_isSome_optFlag = self.optFlag != nil if let __bjs_unwrapped_optFlag = self.optFlag { - __bjs_unwrapped_optFlag.bridgeJSLowerStackReturn() + __bjs_unwrapped_optFlag.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_optFlag ? 1 : 0) } @@ -3243,7 +3241,7 @@ extension Address: _BridgedSwiftStruct { self.city.bridgeJSLowerStackReturn() let __bjs_isSome_zipCode = self.zipCode != nil if let __bjs_unwrapped_zipCode = self.zipCode { - __bjs_unwrapped_zipCode.bridgeJSLowerStackReturn() + __bjs_unwrapped_zipCode.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_zipCode ? 1 : 0) } @@ -3297,12 +3295,12 @@ extension Contact: _BridgedSwiftStruct { self.address.bridgeJSLowerReturn() let __bjs_isSome_email = self.email != nil if let __bjs_unwrapped_email = self.email { - __bjs_unwrapped_email.bridgeJSLowerStackReturn() + __bjs_unwrapped_email.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_email ? 1 : 0) let __bjs_isSome_secondaryAddress = self.secondaryAddress != nil if let __bjs_unwrapped_secondaryAddress = self.secondaryAddress { - __bjs_unwrapped_secondaryAddress.bridgeJSLowerReturn() + __bjs_unwrapped_secondaryAddress.bridgeJSLowerReturn() } _swift_js_push_i32(__bjs_isSome_secondaryAddress ? 1 : 0) } @@ -3353,12 +3351,12 @@ extension Config: _BridgedSwiftStruct { self.name.bridgeJSLowerStackReturn() let __bjs_isSome_theme = self.theme != nil if let __bjs_unwrapped_theme = self.theme { - __bjs_unwrapped_theme.bridgeJSLowerStackReturn() + __bjs_unwrapped_theme.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_theme ? 1 : 0) let __bjs_isSome_direction = self.direction != nil if let __bjs_unwrapped_direction = self.direction { - __bjs_unwrapped_direction.bridgeJSLowerStackReturn() + __bjs_unwrapped_direction.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_direction ? 1 : 0) self.status.bridgeJSLowerStackReturn() @@ -3408,7 +3406,7 @@ extension SessionData: _BridgedSwiftStruct { self.id.bridgeJSLowerStackReturn() let __bjs_isSome_owner = self.owner != nil if let __bjs_unwrapped_owner = self.owner { - __bjs_unwrapped_owner.bridgeJSLowerStackReturn() + __bjs_unwrapped_owner.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_owner ? 1 : 0) } @@ -3460,12 +3458,12 @@ extension ValidationReport: _BridgedSwiftStruct { self.result.bridgeJSLowerReturn() let __bjs_isSome_status = self.status != nil if let __bjs_unwrapped_status = self.status { - __bjs_unwrapped_status.bridgeJSLowerStackReturn() + __bjs_unwrapped_status.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_status ? 1 : 0) let __bjs_isSome_outcome = self.outcome != nil if let __bjs_unwrapped_outcome = self.outcome { - _swift_js_push_i32(__bjs_unwrapped_outcome.bridgeJSLowerParameter()) + _swift_js_push_i32(__bjs_unwrapped_outcome.bridgeJSLowerParameter()) } _swift_js_push_i32(__bjs_isSome_outcome ? 1 : 0) } @@ -3526,23 +3524,23 @@ extension AdvancedConfig: _BridgedSwiftStruct { self.status.bridgeJSLowerStackReturn() let __bjs_isSome_result = self.result != nil if let __bjs_unwrapped_result = self.result { - _swift_js_push_i32(__bjs_unwrapped_result.bridgeJSLowerParameter()) + _swift_js_push_i32(__bjs_unwrapped_result.bridgeJSLowerParameter()) } _swift_js_push_i32(__bjs_isSome_result ? 1 : 0) let __bjs_isSome_metadata = self.metadata != nil if let __bjs_unwrapped_metadata = self.metadata { - __bjs_unwrapped_metadata.bridgeJSLowerStackReturn() + __bjs_unwrapped_metadata.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_metadata ? 1 : 0) let __bjs_isSome_location = self.location != nil if let __bjs_unwrapped_location = self.location { - __bjs_unwrapped_location.bridgeJSLowerReturn() + __bjs_unwrapped_location.bridgeJSLowerReturn() } _swift_js_push_i32(__bjs_isSome_location ? 1 : 0) self.defaults.bridgeJSLowerReturn() let __bjs_isSome_overrideDefaults = self.overrideDefaults != nil if let __bjs_unwrapped_overrideDefaults = self.overrideDefaults { - __bjs_unwrapped_overrideDefaults.bridgeJSLowerReturn() + __bjs_unwrapped_overrideDefaults.bridgeJSLowerReturn() } _swift_js_push_i32(__bjs_isSome_overrideDefaults ? 1 : 0) } @@ -3594,12 +3592,12 @@ extension MeasurementConfig: _BridgedSwiftStruct { self.ratio.bridgeJSLowerStackReturn() let __bjs_isSome_optionalPrecision = self.optionalPrecision != nil if let __bjs_unwrapped_optionalPrecision = self.optionalPrecision { - __bjs_unwrapped_optionalPrecision.bridgeJSLowerStackReturn() + __bjs_unwrapped_optionalPrecision.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_optionalPrecision ? 1 : 0) let __bjs_isSome_optionalRatio = self.optionalRatio != nil if let __bjs_unwrapped_optionalRatio = self.optionalRatio { - __bjs_unwrapped_optionalRatio.bridgeJSLowerStackReturn() + __bjs_unwrapped_optionalRatio.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_optionalRatio ? 1 : 0) } @@ -3735,7 +3733,7 @@ extension CopyableCart: _BridgedSwiftStruct { self.x.bridgeJSLowerStackReturn() let __bjs_isSome_note = self.note != nil if let __bjs_unwrapped_note = self.note { - __bjs_unwrapped_note.bridgeJSLowerStackReturn() + __bjs_unwrapped_note.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_note ? 1 : 0) } @@ -3842,7 +3840,7 @@ extension CopyableNestedCart: _BridgedSwiftStruct { self.item.bridgeJSLowerReturn() let __bjs_isSome_shippingAddress = self.shippingAddress != nil if let __bjs_unwrapped_shippingAddress = self.shippingAddress { - __bjs_unwrapped_shippingAddress.bridgeJSLowerReturn() + __bjs_unwrapped_shippingAddress.bridgeJSLowerReturn() } _swift_js_push_i32(__bjs_isSome_shippingAddress ? 1 : 0) } @@ -4011,7 +4009,7 @@ extension JSObjectContainer: _BridgedSwiftStruct { self.object.bridgeJSLowerStackReturn() let __bjs_isSome_optionalObject = self.optionalObject != nil if let __bjs_unwrapped_optionalObject = self.optionalObject { - __bjs_unwrapped_optionalObject.bridgeJSLowerStackReturn() + __bjs_unwrapped_optionalObject.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_optionalObject ? 1 : 0) } @@ -4051,9 +4049,7 @@ fileprivate func _bjs_struct_lift_JSObjectContainer() -> Int32 { extension FooContainer: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> FooContainer { - let optionalFoo = Optional.bridgeJSLiftParameter().map { - Foo(unsafelyWrapping: $0) - } + let optionalFoo = Optional.bridgeJSLiftParameter().map { Foo(unsafelyWrapping: $0) } let foo = Foo(unsafelyWrapping: JSObject.bridgeJSLiftParameter()) return FooContainer(foo: foo, optionalFoo: optionalFoo) } @@ -4062,7 +4058,7 @@ extension FooContainer: _BridgedSwiftStruct { self.foo.jsObject.bridgeJSLowerStackReturn() let __bjs_isSome_optionalFoo = self.optionalFoo != nil if let __bjs_unwrapped_optionalFoo = self.optionalFoo { - __bjs_unwrapped_optionalFoo.jsObject.bridgeJSLowerStackReturn() + __bjs_unwrapped_optionalFoo.jsObject.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_optionalFoo ? 1 : 0) } @@ -4109,7 +4105,7 @@ extension ArrayMembers: _BridgedSwiftStruct { } else { return [String].bridgeJSLiftParameter() } - }() +}() let ints = [Int].bridgeJSLiftParameter() return ArrayMembers(ints: ints, optStrings: optStrings) } @@ -4118,7 +4114,7 @@ extension ArrayMembers: _BridgedSwiftStruct { self.ints.bridgeJSLowerReturn() let __bjs_isSome_optStrings = self.optStrings != nil if let __bjs_unwrapped_optStrings = self.optStrings { - __bjs_unwrapped_optStrings.bridgeJSLowerReturn() + __bjs_unwrapped_optStrings.bridgeJSLowerReturn() } _swift_js_push_i32(__bjs_isSome_optStrings ? 1 : 0) } @@ -4396,10 +4392,11 @@ public func _bjs_roundTripOptionalJSValueArray(_ v: Int32) -> Void { } else { return [JSValue].bridgeJSLiftParameter() } - }()) + }()) let __bjs_isSome_ret = ret != nil if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn()} + __bjs_unwrapped_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) #else fatalError("Only available on WebAssembly") @@ -4636,7 +4633,7 @@ public func _bjs_asyncRoundTripVoid() -> Int32 { #if arch(wasm32) let ret = JSPromise.async { await asyncRoundTripVoid() - } .jsObject + }.jsObject return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -4649,7 +4646,7 @@ public func _bjs_asyncRoundTripInt(_ v: Int32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { return await asyncRoundTripInt(v: Int.bridgeJSLiftParameter(v)).jsValue - } .jsObject + }.jsObject return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -4662,7 +4659,7 @@ public func _bjs_asyncRoundTripFloat(_ v: Float32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { return await asyncRoundTripFloat(v: Float.bridgeJSLiftParameter(v)).jsValue - } .jsObject + }.jsObject return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -4675,7 +4672,7 @@ public func _bjs_asyncRoundTripDouble(_ v: Float64) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { return await asyncRoundTripDouble(v: Double.bridgeJSLiftParameter(v)).jsValue - } .jsObject + }.jsObject return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -4688,7 +4685,7 @@ public func _bjs_asyncRoundTripBool(_ v: Int32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { return await asyncRoundTripBool(v: Bool.bridgeJSLiftParameter(v)).jsValue - } .jsObject + }.jsObject return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -4701,7 +4698,7 @@ public func _bjs_asyncRoundTripString(_ vBytes: Int32, _ vLength: Int32) -> Int3 #if arch(wasm32) let ret = JSPromise.async { return await asyncRoundTripString(v: String.bridgeJSLiftParameter(vBytes, vLength)).jsValue - } .jsObject + }.jsObject return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -4714,7 +4711,7 @@ public func _bjs_asyncRoundTripSwiftHeapObject(_ v: UnsafeMutableRawPointer) -> #if arch(wasm32) let ret = JSPromise.async { return await asyncRoundTripSwiftHeapObject(v: Greeter.bridgeJSLiftParameter(v)).jsValue - } .jsObject + }.jsObject return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -4727,7 +4724,7 @@ public func _bjs_asyncRoundTripJSObject(_ v: Int32) -> Int32 { #if arch(wasm32) let ret = JSPromise.async { return await asyncRoundTripJSObject(v: JSObject.bridgeJSLiftParameter(v)).jsValue - } .jsObject + }.jsObject return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -5424,7 +5421,7 @@ public func _bjs_arrayWithOptionalDefault(_ values: Int32) -> Int32 { } else { return [Int].bridgeJSLiftParameter() } - }()) + }()) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -5593,17 +5590,19 @@ public func _bjs_roundTripOptionalIntArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Optional.bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -5618,17 +5617,19 @@ public func _bjs_roundTripOptionalStringArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Optional.bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -5643,17 +5644,19 @@ public func _bjs_roundTripOptionalDataPointArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Optional.bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.bridgeJSLowerReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -5668,17 +5671,19 @@ public func _bjs_roundTripOptionalDirectionArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Optional.bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -5693,17 +5698,19 @@ public func _bjs_roundTripOptionalStatusArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Optional.bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -5720,10 +5727,11 @@ public func _bjs_roundTripOptionalIntArrayType(_ values: Int32) -> Void { } else { return [Int].bridgeJSLiftParameter() } - }()) + }()) let __bjs_isSome_ret = ret != nil if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn()} + __bjs_unwrapped_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) #else fatalError("Only available on WebAssembly") @@ -5740,10 +5748,11 @@ public func _bjs_roundTripOptionalStringArrayType(_ values: Int32) -> Void { } else { return [String].bridgeJSLiftParameter() } - }()) + }()) let __bjs_isSome_ret = ret != nil if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn()} + __bjs_unwrapped_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) #else fatalError("Only available on WebAssembly") @@ -5760,10 +5769,11 @@ public func _bjs_roundTripOptionalGreeterArrayType(_ greeters: Int32) -> Void { } else { return [Greeter].bridgeJSLiftParameter() } - }()) + }()) let __bjs_isSome_ret = ret != nil if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn()} + __bjs_unwrapped_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) #else fatalError("Only available on WebAssembly") @@ -5778,14 +5788,15 @@ public func _bjs_roundTripNestedIntArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [[Int]] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append([Int].bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn()} + __bjs_elem_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -5800,14 +5811,15 @@ public func _bjs_roundTripNestedStringArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [[String]] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append([String].bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn()} + __bjs_elem_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -5822,14 +5834,15 @@ public func _bjs_roundTripNestedDoubleArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [[Double]] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append([Double].bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn()} + __bjs_elem_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -5844,14 +5857,15 @@ public func _bjs_roundTripNestedBoolArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [[Bool]] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append([Bool].bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn()} + __bjs_elem_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -5866,14 +5880,15 @@ public func _bjs_roundTripNestedDataPointArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [[DataPoint]] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append([DataPoint].bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn()} + __bjs_elem_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -5888,14 +5903,15 @@ public func _bjs_roundTripNestedDirectionArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [[Direction]] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append([Direction].bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn()} + __bjs_elem_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -5910,14 +5926,15 @@ public func _bjs_roundTripNestedGreeterArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [[Greeter]] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append([Greeter].bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn()} + __bjs_elem_ret.bridgeJSLowerReturn() + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -5995,9 +6012,7 @@ public func _bjs_consumeDataProcessorArrayType() -> Int32 { public func _bjs_roundTripDataProcessorArrayType() -> Void { #if arch(wasm32) let ret = roundTripDataProcessorArrayType(_: [AnyDataProcessor].bridgeJSLiftParameter()) - ret.map { - $0 as! AnyDataProcessor - } .bridgeJSLowerReturn() + ret.map { $0 as! AnyDataProcessor }.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -6022,17 +6037,19 @@ public func _bjs_roundTripOptionalJSObjectArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Optional.bridgeJSLiftParameter()) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.bridgeJSLowerStackReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -6047,15 +6064,13 @@ public func _bjs_roundTripFooArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [Foo] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { + for _ in 0..<__count { __result.append(Foo(unsafelyWrapping: JSObject.bridgeJSLiftParameter())) } __result.reverse() return __result - }()) - ret.map { - $0.jsObject - } .bridgeJSLowerReturn() + }()) + ret.map { $0.jsObject }.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -6069,19 +6084,19 @@ public func _bjs_roundTripOptionalFooArray() -> Void { let __count = Int(_swift_js_pop_i32()) var __result: [Optional] = [] __result.reserveCapacity(__count) - for _ in 0 ..< __count { - __result.append(Optional.bridgeJSLiftParameter().map { - Foo(unsafelyWrapping: $0) - }) + for _ in 0..<__count { + __result.append(Optional.bridgeJSLiftParameter().map { Foo(unsafelyWrapping: $0) }) } __result.reverse() return __result - }()) + }()) for __bjs_elem_ret in ret { let __bjs_isSome_ret_elem = __bjs_elem_ret != nil if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.jsObject.bridgeJSLowerStackReturn()} - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + __bjs_unwrapped_ret_elem.jsObject.bridgeJSLowerStackReturn() + } + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + } _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") @@ -8160,9 +8175,7 @@ public func _bjs_DataProcessorManager_processor_set(_ _self: UnsafeMutableRawPoi @_cdecl("bjs_DataProcessorManager_backupProcessor_get") public func _bjs_DataProcessorManager_backupProcessor_get(_ _self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let ret = DataProcessorManager.bridgeJSLiftParameter(_self).backupProcessor.flatMap { - $0 as? AnyDataProcessor - } + let ret = DataProcessorManager.bridgeJSLiftParameter(_self).backupProcessor.flatMap { $0 as? AnyDataProcessor } return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") From bed117819acf36b3068efc3c93d8e63c4c536560 Mon Sep 17 00:00:00 2001 From: Krzysztof Rodak Date: Wed, 11 Feb 2026 19:13:16 +0100 Subject: [PATCH 28/40] NCF: BridgeJS: Generalize Optional stack ABI for Array, Dictionary, and Struct types --- Benchmarks/Sources/Generated/BridgeJS.swift | 50 +----- .../Sources/BridgeJSCore/ExportSwift.swift | 79 ++------- .../Sources/BridgeJSLink/JSGlueGen.swift | 9 +- .../BridgeJSCodegenTests/ArrayTypes.swift | 22 +-- .../DefaultParameters.swift | 8 +- .../DictionaryTypes.swift | 4 +- .../EnumAssociatedValue.swift | 33 +--- .../BridgeJSCodegenTests/JSValue.swift | 16 +- .../BridgeJSLinkTests/ArrayTypes.js | 3 +- .../BridgeJSLinkTests/DefaultParameters.js | 6 +- .../BridgeJSLinkTests/DictionaryTypes.js | 3 +- .../BridgeJSLinkTests/JSValue.js | 3 +- .../JavaScriptKit/BridgeJSIntrinsics.swift | 81 ++++----- .../Generated/BridgeJS.swift | 164 ++++-------------- 14 files changed, 127 insertions(+), 354 deletions(-) diff --git a/Benchmarks/Sources/Generated/BridgeJS.swift b/Benchmarks/Sources/Generated/BridgeJS.swift index 515d3a531..e4e147f5b 100644 --- a/Benchmarks/Sources/Generated/BridgeJS.swift +++ b/Benchmarks/Sources/Generated/BridgeJS.swift @@ -1762,11 +1762,7 @@ public func _bjs_ArrayRoundtrip_makeOptionalPointArray(_ _self: UnsafeMutableRaw #if arch(wasm32) let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeOptionalPointArray() for __bjs_elem_ret in ret { - let __bjs_isSome_ret_elem = __bjs_elem_ret != nil - if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + __bjs_elem_ret.bridgeJSLowerReturn() } _swift_js_push_i32(Int32(ret.count)) #else @@ -1789,11 +1785,7 @@ public func _bjs_ArrayRoundtrip_roundtripOptionalPointArray(_ _self: UnsafeMutab return __result }()) for __bjs_elem_ret in ret { - let __bjs_isSome_ret_elem = __bjs_elem_ret != nil - if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + __bjs_elem_ret.bridgeJSLowerReturn() } _swift_js_push_i32(Int32(ret.count)) #else @@ -1803,15 +1795,9 @@ public func _bjs_ArrayRoundtrip_roundtripOptionalPointArray(_ _self: UnsafeMutab @_expose(wasm, "bjs_ArrayRoundtrip_takeOptionalArray") @_cdecl("bjs_ArrayRoundtrip_takeOptionalArray") -public func _bjs_ArrayRoundtrip_takeOptionalArray(_ _self: UnsafeMutableRawPointer, _ values: Int32) -> Void { +public func _bjs_ArrayRoundtrip_takeOptionalArray(_ _self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - ArrayRoundtrip.bridgeJSLiftParameter(_self).takeOptionalArray(_: { - if values == 0 { - return Optional<[Int]>.none - } else { - return [Int].bridgeJSLiftParameter() - } - }()) + ArrayRoundtrip.bridgeJSLiftParameter(_self).takeOptionalArray(_: Optional<[Int]>.bridgeJSLiftParameter()) #else fatalError("Only available on WebAssembly") #endif @@ -1822,11 +1808,7 @@ public func _bjs_ArrayRoundtrip_takeOptionalArray(_ _self: UnsafeMutableRawPoint public func _bjs_ArrayRoundtrip_makeOptionalArraySome(_ _self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeOptionalArraySome() - let __bjs_isSome_ret = ret != nil - if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1837,11 +1819,7 @@ public func _bjs_ArrayRoundtrip_makeOptionalArraySome(_ _self: UnsafeMutableRawP public func _bjs_ArrayRoundtrip_makeOptionalArrayNone(_ _self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeOptionalArrayNone() - let __bjs_isSome_ret = ret != nil - if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1849,20 +1827,10 @@ public func _bjs_ArrayRoundtrip_makeOptionalArrayNone(_ _self: UnsafeMutableRawP @_expose(wasm, "bjs_ArrayRoundtrip_roundtripOptionalArray") @_cdecl("bjs_ArrayRoundtrip_roundtripOptionalArray") -public func _bjs_ArrayRoundtrip_roundtripOptionalArray(_ _self: UnsafeMutableRawPointer, _ values: Int32) -> Void { +public func _bjs_ArrayRoundtrip_roundtripOptionalArray(_ _self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).roundtripOptionalArray(_: { - if values == 0 { - return Optional<[Int]>.none - } else { - return [Int].bridgeJSLiftParameter() - } - }()) - let __bjs_isSome_ret = ret != nil - if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).roundtripOptionalArray(_: Optional<[Int]>.bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index 2d31cd212..b75f9535d 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -147,27 +147,7 @@ public class ExportSwift { } else { optionalSwiftType = "JSUndefinedOr" } - if case .array(let elementType) = wrappedType { - let arrayLift = StackCodegen().liftArrayExpression(elementType: elementType) - let isSomeParam = argumentsToLift[0] - let swiftTypeName = elementType.swiftType - typeNameForIntrinsic = "\(optionalSwiftType)<[\(swiftTypeName)]>" - let absentExpr = - kind == .null - ? "\(optionalSwiftType)<[\(swiftTypeName)]>.none" - : "\(optionalSwiftType)<[\(swiftTypeName)]>.undefined" - liftingExpr = ExprSyntax( - """ - { - if \(raw: isSomeParam) == 0 { - return \(raw: absentExpr) - } else { - return \(arrayLift) - } - }() - """ - ) - } else if case .swiftProtocol(let protocolName) = wrappedType { + if case .swiftProtocol(let protocolName) = wrappedType { let wrapperName = "Any\(protocolName)" typeNameForIntrinsic = "\(optionalSwiftType)<\(wrapperName)>" liftingExpr = ExprSyntax( @@ -919,43 +899,11 @@ struct StackCodegen { let typeName = kind == .null ? "Optional" : "JSUndefinedOr" switch wrappedType { case .string, .int, .uint, .bool, .float, .double, .jsObject(nil), .jsValue, - .swiftStruct, .swiftHeapObject, .caseEnum, .associatedValueEnum, .rawValueEnum: + .swiftStruct, .swiftHeapObject, .caseEnum, .associatedValueEnum, .rawValueEnum, + .array, .dictionary: return "\(raw: typeName)<\(raw: wrappedType.swiftType)>.bridgeJSLiftParameter()" case .jsObject(let className?): return "\(raw: typeName).bridgeJSLiftParameter().map { \(raw: className)(unsafelyWrapping: $0) }" - case .array(let elementType): - let arrayLift = liftArrayExpression(elementType: elementType) - let swiftTypeName = elementType.swiftType - let absentExpr = - kind == .null - ? "\(typeName)<[\(swiftTypeName)]>.none" : "\(typeName)<[\(swiftTypeName)]>.undefined" - return """ - { - let __isSome = _swift_js_pop_i32() - if __isSome == 0 { - return \(raw: absentExpr) - } else { - return \(arrayLift) - } - }() - """ - case .dictionary(let valueType): - let dictionaryLift = liftDictionaryExpression(valueType: valueType) - let swiftTypeName = valueType.swiftType - let absentExpr = - kind == .null - ? "\(typeName)<[String: \(swiftTypeName)]>.none" - : "\(typeName)<[String: \(swiftTypeName)]>.undefined" - return """ - { - let __isSome = _swift_js_pop_i32() - if __isSome == 0 { - return \(raw: absentExpr) - } else { - return \(dictionaryLift) - } - }() - """ case .nullable, .void, .namespaceEnum, .closure, .unsafePointer, .swiftProtocol: fatalError("Invalid nullable wrapped type: \(wrappedType)") } @@ -1112,6 +1060,13 @@ struct StackCodegen { accessor: String, varPrefix: String ) -> [CodeBlockItemSyntax] { + switch wrappedType { + case .array, .dictionary, .swiftStruct: + return ["\(raw: accessor).bridgeJSLowerReturn()"] + default: + break + } + var statements: [String] = [] statements.append("let __bjs_isSome_\(varPrefix) = \(accessor) != nil") statements.append("if let __bjs_unwrapped_\(varPrefix) = \(accessor) {") @@ -1140,23 +1095,15 @@ struct StackCodegen { case .string, .int, .uint, .bool, .float, .double, .jsValue: return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"] case .caseEnum, .rawValueEnum: - // Enums conform to _BridgedSwiftStackType return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"] - case .swiftStruct: - return ["\(raw: unwrappedVar).bridgeJSLowerReturn()"] case .swiftHeapObject: return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"] case .associatedValueEnum: - // Push payloads via bridgeJSLowerParameter(), then push the returned case ID return ["_swift_js_push_i32(\(raw: unwrappedVar).bridgeJSLowerParameter())"] case .jsObject(nil): return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"] case .jsObject(_?): return ["\(raw: unwrappedVar).jsObject.bridgeJSLowerStackReturn()"] - case .array(let elementType): - return lowerArrayStatements(elementType: elementType, accessor: unwrappedVar, varPrefix: varPrefix) - case .dictionary(let valueType): - return lowerDictionaryStatements(valueType: valueType, accessor: unwrappedVar, varPrefix: varPrefix) default: return ["preconditionFailure(\"BridgeJS: unsupported optional wrapped type\")"] } @@ -1834,8 +1781,12 @@ extension BridgeType { case .swiftProtocol: return .jsObject case .void: return .void case .nullable(let wrappedType, _): + let wrappedInfo = try wrappedType.liftParameterInfo() + if wrappedInfo.parameters.isEmpty { + return LiftingIntrinsicInfo(parameters: []) + } var optionalParams: [(name: String, type: WasmCoreType)] = [("isSome", .i32)] - optionalParams.append(contentsOf: try wrappedType.liftParameterInfo().parameters) + optionalParams.append(contentsOf: wrappedInfo.parameters) return LiftingIntrinsicInfo(parameters: optionalParams) case .caseEnum: return .caseEnum case .rawValueEnum(_, let rawType): diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 9f1eddfdd..1e384d833 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -832,7 +832,8 @@ struct IntrinsicJSFragment: Sendable { } printer.write("}") cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") - return ["+\(isSomeVar)"] + printer.write("\(JSGlueVariableScope.reservedI32Stack).push(+\(isSomeVar));") + return [] case .string, .rawValueEnum(_, .string): let bytesVar = scope.variable("\(value)Bytes") let idVar = scope.variable("\(value)Id") @@ -895,7 +896,8 @@ struct IntrinsicJSFragment: Sendable { } printer.write("}") cleanupCode.write("for (const cleanup of \(cleanupArrayVar)) { cleanup(); }") - return ["+\(isSomeVar)"] + printer.write("\(JSGlueVariableScope.reservedI32Stack).push(+\(isSomeVar));") + return [] case .dictionary(let valueType): let cleanupArrayVar = scope.variable("\(value)Cleanups") printer.write("const \(cleanupArrayVar) = [];") @@ -915,7 +917,8 @@ struct IntrinsicJSFragment: Sendable { } printer.write("}") cleanupCode.write("for (const cleanup of \(cleanupArrayVar)) { cleanup(); }") - return ["+\(isSomeVar)"] + printer.write("\(JSGlueVariableScope.reservedI32Stack).push(+\(isSomeVar));") + return [] default: switch wrappedType { case .swiftHeapObject: diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift index 261c0b066..243c99b7c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift @@ -277,20 +277,10 @@ public func _bjs_processOptionalStringArray() -> Void { @_expose(wasm, "bjs_processOptionalArray") @_cdecl("bjs_processOptionalArray") -public func _bjs_processOptionalArray(_ values: Int32) -> Void { +public func _bjs_processOptionalArray() -> Void { #if arch(wasm32) - let ret = processOptionalArray(_: { - if values == 0 { - return Optional<[Int]>.none - } else { - return [Int].bridgeJSLiftParameter() - } - }()) - let __bjs_isSome_ret = ret != nil - if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) + let ret = processOptionalArray(_: Optional<[Int]>.bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -311,11 +301,7 @@ public func _bjs_processOptionalPointArray() -> Void { return __result }()) for __bjs_elem_ret in ret { - let __bjs_isSome_ret_elem = __bjs_elem_ret != nil - if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + __bjs_elem_ret.bridgeJSLowerReturn() } _swift_js_push_i32(Int32(ret.count)) #else diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.swift index 4c4c69c99..16cae49e8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.swift @@ -294,9 +294,9 @@ public func _bjs_testEmptyInit(_ greeter: UnsafeMutableRawPointer) -> UnsafeMuta @_expose(wasm, "bjs_testOptionalStructDefault") @_cdecl("bjs_testOptionalStructDefault") -public func _bjs_testOptionalStructDefault(_ point: Int32) -> Void { +public func _bjs_testOptionalStructDefault() -> Void { #if arch(wasm32) - let ret = testOptionalStructDefault(point: Optional.bridgeJSLiftParameter(point)) + let ret = testOptionalStructDefault(point: Optional.bridgeJSLiftParameter()) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -305,9 +305,9 @@ public func _bjs_testOptionalStructDefault(_ point: Int32) -> Void { @_expose(wasm, "bjs_testOptionalStructWithValueDefault") @_cdecl("bjs_testOptionalStructWithValueDefault") -public func _bjs_testOptionalStructWithValueDefault(_ point: Int32) -> Void { +public func _bjs_testOptionalStructWithValueDefault() -> Void { #if arch(wasm32) - let ret = testOptionalStructWithValueDefault(point: Optional.bridgeJSLiftParameter(point)) + let ret = testOptionalStructWithValueDefault(point: Optional.bridgeJSLiftParameter()) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DictionaryTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DictionaryTypes.swift index 2a41c35a7..016a5f814 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DictionaryTypes.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DictionaryTypes.swift @@ -11,9 +11,9 @@ public func _bjs_mirrorDictionary() -> Void { @_expose(wasm, "bjs_optionalDictionary") @_cdecl("bjs_optionalDictionary") -public func _bjs_optionalDictionary(_ values: Int32) -> Void { +public func _bjs_optionalDictionary() -> Void { #if arch(wasm32) - let ret = optionalDictionary(_: Optional<[String: String]>.bridgeJSLiftParameter(values)) + let ret = optionalDictionary(_: Optional<[String: String]>.bridgeJSLiftParameter()) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift index f2029749c..a21c766c0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift @@ -617,14 +617,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { case 3: return .optNestedEnum(Optional.bridgeJSLiftParameter()) case 4: - return .optArray({ - let __isSome = _swift_js_pop_i32() - if __isSome == 0 { - return Optional<[Int]>.none - } else { - return [Int].bridgeJSLiftParameter() - } -}()) + return .optArray(Optional<[Int]>.bridgeJSLiftParameter()) case 5: return .empty default: @@ -637,11 +630,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { switch self { case .optStruct(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + param0.bridgeJSLowerReturn() return Int32(0) case .optClass(let param0): let __bjs_isSome_param0 = param0 != nil @@ -665,11 +654,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(3) case .optArray(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + param0.bridgeJSLowerReturn() return Int32(4) case .empty: return Int32(5) @@ -689,11 +674,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { switch self { case .optStruct(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + param0.bridgeJSLowerReturn() _swift_js_push_tag(Int32(0)) case .optClass(let param0): let __bjs_isSome_param0 = param0 != nil @@ -717,11 +698,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(3)) case .optArray(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + param0.bridgeJSLowerReturn() _swift_js_push_tag(Int32(4)) case .empty: _swift_js_push_tag(Int32(5)) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.swift index b4e45bbc9..931605a50 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.swift @@ -33,20 +33,10 @@ public func _bjs_roundTripJSValueArray() -> Void { @_expose(wasm, "bjs_roundTripOptionalJSValueArray") @_cdecl("bjs_roundTripOptionalJSValueArray") -public func _bjs_roundTripOptionalJSValueArray(_ values: Int32) -> Void { +public func _bjs_roundTripOptionalJSValueArray() -> Void { #if arch(wasm32) - let ret = roundTripOptionalJSValueArray(_: { - if values == 0 { - return Optional<[JSValue]>.none - } else { - return [JSValue].bridgeJSLiftParameter() - } - }()) - let __bjs_isSome_ret = ret != nil - if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) + let ret = roundTripOptionalJSValueArray(_: Optional<[JSValue]>.bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js index d858d8e38..a381f5569 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js @@ -673,7 +673,8 @@ export async function createInstantiator(options, swift) { i32Stack.push(values.length); valuesCleanups.push(() => { for (const cleanup of arrayCleanups) { cleanup(); } }); } - instance.exports.bjs_processOptionalArray(+isSome); + i32Stack.push(+isSome); + instance.exports.bjs_processOptionalArray(); const isSome1 = i32Stack.pop(); let optResult; if (isSome1) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js index 079618bbf..04335c58c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js @@ -521,7 +521,8 @@ export async function createInstantiator(options, swift) { const structResult = structHelpers.Config.lower(point); pointCleanup = structResult.cleanup; } - instance.exports.bjs_testOptionalStructDefault(+isSome); + i32Stack.push(+isSome); + instance.exports.bjs_testOptionalStructDefault(); const isSome1 = i32Stack.pop(); let optResult; if (isSome1) { @@ -539,7 +540,8 @@ export async function createInstantiator(options, swift) { const structResult = structHelpers.Config.lower(point); pointCleanup = structResult.cleanup; } - instance.exports.bjs_testOptionalStructWithValueDefault(+isSome); + i32Stack.push(+isSome); + instance.exports.bjs_testOptionalStructWithValueDefault(); const isSome1 = i32Stack.pop(); let optResult; if (isSome1) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js index 54f00021d..a77407eca 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js @@ -327,7 +327,8 @@ export async function createInstantiator(options, swift) { i32Stack.push(entries.length); valuesCleanups.push(() => { for (const cleanup of arrayCleanups) { cleanup(); } }); } - instance.exports.bjs_optionalDictionary(+isSome); + i32Stack.push(+isSome); + instance.exports.bjs_optionalDictionary(); const isSome1 = i32Stack.pop(); let optResult; if (isSome1) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js index 888a11a4c..f6e4bf8aa 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js @@ -507,7 +507,8 @@ export async function createInstantiator(options, swift) { i32Stack.push(values.length); valuesCleanups.push(() => { for (const cleanup of arrayCleanups) { cleanup(); } }); } - instance.exports.bjs_roundTripOptionalJSValueArray(+isSome); + i32Stack.push(+isSome); + instance.exports.bjs_roundTripOptionalJSValueArray(); const isSome1 = i32Stack.pop(); let optResult; if (isSome1) { diff --git a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift index 496b515c9..d1390a610 100644 --- a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift +++ b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift @@ -623,7 +623,7 @@ extension _BridgedSwiftAssociatedValueEnum { /// A protocol that Swift struct types conform to. /// /// The conformance is automatically synthesized by the BridgeJS code generator. -public protocol _BridgedSwiftStruct: _BridgedSwiftTypeLoweredIntoVoidType, _BridgedSwiftStackType { +public protocol _BridgedSwiftStruct: _BridgedSwiftTypeLoweredIntoVoidType, _BridgedSwiftGenericOptionalStackType { // MARK: ExportSwift @_spi(BridgeJS) static func bridgeJSLiftParameter() -> Self @_spi(BridgeJS) consuming func bridgeJSLowerReturn() -> Void @@ -1463,11 +1463,6 @@ extension Optional where Wrapped == [JSValue] { return [JSValue].bridgeJSLiftParameter() } - @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> [JSValue]? { - let isSome = _swift_js_pop_i32() - return bridgeJSLiftParameter(isSome) - } - @_spi(BridgeJS) public static func bridgeJSLiftReturn() -> [JSValue]? { let isSome = _swift_js_pop_i32() if isSome == 0 { @@ -1741,17 +1736,6 @@ public protocol _BridgedSwiftTypeLoweredIntoVoidType { consuming func bridgeJSLowerReturn() -> Void } -extension Optional where Wrapped: _BridgedSwiftTypeLoweredIntoVoidType { - @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - switch consume self { - case .none: - () - case .some(let value): - value.bridgeJSLowerReturn() - } - } -} - // MARK: Optional Raw Value Enum Support extension Optional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == String { @@ -1989,8 +1973,6 @@ extension Optional where Wrapped: _BridgedSwiftAssociatedValueEnum { // MARK: Optional Struct Support extension Optional where Wrapped: _BridgedSwiftStruct { - // MARK: ExportSwift - @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32) -> Wrapped? { if isSome == 0 { return nil @@ -1998,19 +1980,40 @@ extension Optional where Wrapped: _BridgedSwiftStruct { return Wrapped.bridgeJSLiftParameter() } } +} + +// MARK: - Generic Optional Stack Support + +/// Marker protocol for types whose Optional wrapper should use the generic +/// stack-based ABI (`_BridgedSwiftStackType`). Only Array, Dictionary, and +/// `_BridgedSwiftStruct` conform. Primitives and other types keep their +/// own type-specific Optional extensions. +public protocol _BridgedSwiftGenericOptionalStackType: _BridgedSwiftStackType +where StackLiftResult == Self {} + +extension Optional: _BridgedSwiftStackType +where Wrapped: _BridgedSwiftGenericOptionalStackType { + public typealias StackLiftResult = Wrapped? @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Wrapped? { let isSome = _swift_js_pop_i32() - return bridgeJSLiftParameter(isSome) + if isSome == 0 { + return nil + } + return Wrapped.bridgeJSLiftParameter() + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerStackReturn() { + bridgeJSLowerReturn() } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { switch consume self { case .none: - _swift_js_push_i32(0) // Push only isSome=0 (no struct fields) + _swift_js_push_i32(0) case .some(let value): - value.bridgeJSLowerReturn() // Push all struct fields FIRST - _swift_js_push_i32(1) // Then push isSome=1 LAST (so it's popped FIRST by JS) + value.bridgeJSLowerStackReturn() + _swift_js_push_i32(1) } } } @@ -2235,12 +2238,6 @@ extension _BridgedAsOptional where Wrapped: _BridgedSwiftCaseEnum { } } -extension _BridgedAsOptional where Wrapped: _BridgedSwiftTypeLoweredIntoVoidType { - @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - asOptional.bridgeJSLowerReturn() - } -} - extension _BridgedAsOptional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == String { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { @@ -2390,6 +2387,8 @@ extension _BridgedAsOptional where Wrapped: _BridgedSwiftStruct { // MARK: - Array Support +extension Array: _BridgedSwiftGenericOptionalStackType +where Element: _BridgedSwiftStackType, Element.StackLiftResult == Element {} extension Array: _BridgedSwiftStackType where Element: _BridgedSwiftStackType, Element.StackLiftResult == Element { public typealias StackLiftResult = [Element] @@ -2427,11 +2426,15 @@ extension Array: _BridgedSwiftStackType where Element: _BridgedSwiftStackType, E // MARK: - Dictionary Support -public protocol _BridgedSwiftDictionaryStackType: _BridgedSwiftTypeLoweredIntoVoidType { +public protocol _BridgedSwiftDictionaryStackType: _BridgedSwiftTypeLoweredIntoVoidType, + _BridgedSwiftGenericOptionalStackType +{ associatedtype DictionaryValue: _BridgedSwiftStackType where DictionaryValue.StackLiftResult == DictionaryValue } +extension Dictionary: _BridgedSwiftGenericOptionalStackType +where Key == String, Value: _BridgedSwiftStackType, Value.StackLiftResult == Value {} extension Dictionary: _BridgedSwiftStackType where Key == String, Value: _BridgedSwiftStackType, Value.StackLiftResult == Value { public typealias StackLiftResult = [String: Value] @@ -2492,16 +2495,6 @@ extension Optional where Wrapped: _BridgedSwiftDictionaryStackType { } } - @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() { - switch consume self { - case .none: - _swift_js_push_i32(0) - case .some(let dict): - dict.bridgeJSLowerReturn() - _swift_js_push_i32(1) - } - } - @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32) -> [String: Wrapped.DictionaryValue]? { if isSome == 0 { return nil @@ -2509,10 +2502,6 @@ extension Optional where Wrapped: _BridgedSwiftDictionaryStackType { return Dictionary.bridgeJSLiftParameter() } - @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> [String: Wrapped.DictionaryValue]? { - bridgeJSLiftParameter(_swift_js_pop_i32()) - } - @_spi(BridgeJS) public static func bridgeJSLiftReturn() -> [String: Wrapped.DictionaryValue]? { let isSome = _swift_js_pop_i32() if isSome == 0 { @@ -2542,4 +2531,8 @@ extension _BridgedAsOptional where Wrapped: _BridgedSwiftDictionaryStackType { let value = Dictionary.bridgeJSLiftParameter() as! Wrapped return Self(optional: value) } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + asOptional.bridgeJSLowerReturn() + } } diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index af9f15dbc..9465040a9 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -2814,14 +2814,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { case 3: return .optNestedEnum(Optional.bridgeJSLiftParameter()) case 4: - return .optArray({ - let __isSome = _swift_js_pop_i32() - if __isSome == 0 { - return Optional<[Int]>.none - } else { - return [Int].bridgeJSLiftParameter() - } -}()) + return .optArray(Optional<[Int]>.bridgeJSLiftParameter()) case 5: return .optJsClass(Optional.bridgeJSLiftParameter().map { Foo(unsafelyWrapping: $0) }) case 6: @@ -2836,11 +2829,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { switch self { case .optStruct(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + param0.bridgeJSLowerReturn() return Int32(0) case .optClass(let param0): let __bjs_isSome_param0 = param0 != nil @@ -2864,11 +2853,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(3) case .optArray(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + param0.bridgeJSLowerReturn() return Int32(4) case .optJsClass(let param0): let __bjs_isSome_param0 = param0 != nil @@ -2895,11 +2880,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { switch self { case .optStruct(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + param0.bridgeJSLowerReturn() _swift_js_push_tag(Int32(0)) case .optClass(let param0): let __bjs_isSome_param0 = param0 != nil @@ -2923,11 +2904,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) _swift_js_push_tag(Int32(3)) case .optArray(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + param0.bridgeJSLowerReturn() _swift_js_push_tag(Int32(4)) case .optJsClass(let param0): let __bjs_isSome_param0 = param0 != nil @@ -3298,11 +3275,7 @@ extension Contact: _BridgedSwiftStruct { __bjs_unwrapped_email.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_email ? 1 : 0) - let __bjs_isSome_secondaryAddress = self.secondaryAddress != nil - if let __bjs_unwrapped_secondaryAddress = self.secondaryAddress { - __bjs_unwrapped_secondaryAddress.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_secondaryAddress ? 1 : 0) + self.secondaryAddress.bridgeJSLowerReturn() } init(unsafelyCopying jsObject: JSObject) { @@ -3532,17 +3505,9 @@ extension AdvancedConfig: _BridgedSwiftStruct { __bjs_unwrapped_metadata.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_metadata ? 1 : 0) - let __bjs_isSome_location = self.location != nil - if let __bjs_unwrapped_location = self.location { - __bjs_unwrapped_location.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_location ? 1 : 0) + self.location.bridgeJSLowerReturn() self.defaults.bridgeJSLowerReturn() - let __bjs_isSome_overrideDefaults = self.overrideDefaults != nil - if let __bjs_unwrapped_overrideDefaults = self.overrideDefaults { - __bjs_unwrapped_overrideDefaults.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_overrideDefaults ? 1 : 0) + self.overrideDefaults.bridgeJSLowerReturn() } init(unsafelyCopying jsObject: JSObject) { @@ -3838,11 +3803,7 @@ extension CopyableNestedCart: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { self.id.bridgeJSLowerStackReturn() self.item.bridgeJSLowerReturn() - let __bjs_isSome_shippingAddress = self.shippingAddress != nil - if let __bjs_unwrapped_shippingAddress = self.shippingAddress { - __bjs_unwrapped_shippingAddress.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_shippingAddress ? 1 : 0) + self.shippingAddress.bridgeJSLowerReturn() } init(unsafelyCopying jsObject: JSObject) { @@ -4098,25 +4059,14 @@ fileprivate func _bjs_struct_lift_FooContainer() -> Int32 { extension ArrayMembers: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> ArrayMembers { - let optStrings = { - let __isSome = _swift_js_pop_i32() - if __isSome == 0 { - return Optional<[String]>.none - } else { - return [String].bridgeJSLiftParameter() - } -}() + let optStrings = Optional<[String]>.bridgeJSLiftParameter() let ints = [Int].bridgeJSLiftParameter() return ArrayMembers(ints: ints, optStrings: optStrings) } @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { self.ints.bridgeJSLowerReturn() - let __bjs_isSome_optStrings = self.optStrings != nil - if let __bjs_unwrapped_optStrings = self.optStrings { - __bjs_unwrapped_optStrings.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_optStrings ? 1 : 0) + self.optStrings.bridgeJSLowerReturn() } init(unsafelyCopying jsObject: JSObject) { @@ -4340,9 +4290,9 @@ public func _bjs_roundTripDictionaryExport() -> Void { @_expose(wasm, "bjs_roundTripOptionalDictionaryExport") @_cdecl("bjs_roundTripOptionalDictionaryExport") -public func _bjs_roundTripOptionalDictionaryExport(_ v: Int32) -> Void { +public func _bjs_roundTripOptionalDictionaryExport() -> Void { #if arch(wasm32) - let ret = roundTripOptionalDictionaryExport(v: Optional<[String: String]>.bridgeJSLiftParameter(v)) + let ret = roundTripOptionalDictionaryExport(v: Optional<[String: String]>.bridgeJSLiftParameter()) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -4384,20 +4334,10 @@ public func _bjs_roundTripJSValueArray() -> Void { @_expose(wasm, "bjs_roundTripOptionalJSValueArray") @_cdecl("bjs_roundTripOptionalJSValueArray") -public func _bjs_roundTripOptionalJSValueArray(_ v: Int32) -> Void { +public func _bjs_roundTripOptionalJSValueArray() -> Void { #if arch(wasm32) - let ret = roundTripOptionalJSValueArray(v: { - if v == 0 { - return Optional<[JSValue]>.none - } else { - return [JSValue].bridgeJSLiftParameter() - } - }()) - let __bjs_isSome_ret = ret != nil - if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) + let ret = roundTripOptionalJSValueArray(v: Optional<[JSValue]>.bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -5413,15 +5353,9 @@ public func _bjs_arrayWithDefault() -> Int32 { @_expose(wasm, "bjs_arrayWithOptionalDefault") @_cdecl("bjs_arrayWithOptionalDefault") -public func _bjs_arrayWithOptionalDefault(_ values: Int32) -> Int32 { +public func _bjs_arrayWithOptionalDefault() -> Int32 { #if arch(wasm32) - let ret = arrayWithOptionalDefault(_: { - if values == 0 { - return Optional<[Int]>.none - } else { - return [Int].bridgeJSLiftParameter() - } - }()) + let ret = arrayWithOptionalDefault(_: Optional<[Int]>.bridgeJSLiftParameter()) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -5651,11 +5585,7 @@ public func _bjs_roundTripOptionalDataPointArray() -> Void { return __result }()) for __bjs_elem_ret in ret { - let __bjs_isSome_ret_elem = __bjs_elem_ret != nil - if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { - __bjs_unwrapped_ret_elem.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0) + __bjs_elem_ret.bridgeJSLowerReturn() } _swift_js_push_i32(Int32(ret.count)) #else @@ -5719,20 +5649,10 @@ public func _bjs_roundTripOptionalStatusArray() -> Void { @_expose(wasm, "bjs_roundTripOptionalIntArrayType") @_cdecl("bjs_roundTripOptionalIntArrayType") -public func _bjs_roundTripOptionalIntArrayType(_ values: Int32) -> Void { +public func _bjs_roundTripOptionalIntArrayType() -> Void { #if arch(wasm32) - let ret = roundTripOptionalIntArrayType(_: { - if values == 0 { - return Optional<[Int]>.none - } else { - return [Int].bridgeJSLiftParameter() - } - }()) - let __bjs_isSome_ret = ret != nil - if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) + let ret = roundTripOptionalIntArrayType(_: Optional<[Int]>.bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -5740,20 +5660,10 @@ public func _bjs_roundTripOptionalIntArrayType(_ values: Int32) -> Void { @_expose(wasm, "bjs_roundTripOptionalStringArrayType") @_cdecl("bjs_roundTripOptionalStringArrayType") -public func _bjs_roundTripOptionalStringArrayType(_ values: Int32) -> Void { +public func _bjs_roundTripOptionalStringArrayType() -> Void { #if arch(wasm32) - let ret = roundTripOptionalStringArrayType(_: { - if values == 0 { - return Optional<[String]>.none - } else { - return [String].bridgeJSLiftParameter() - } - }()) - let __bjs_isSome_ret = ret != nil - if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) + let ret = roundTripOptionalStringArrayType(_: Optional<[String]>.bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -5761,20 +5671,10 @@ public func _bjs_roundTripOptionalStringArrayType(_ values: Int32) -> Void { @_expose(wasm, "bjs_roundTripOptionalGreeterArrayType") @_cdecl("bjs_roundTripOptionalGreeterArrayType") -public func _bjs_roundTripOptionalGreeterArrayType(_ greeters: Int32) -> Void { +public func _bjs_roundTripOptionalGreeterArrayType() -> Void { #if arch(wasm32) - let ret = roundTripOptionalGreeterArrayType(_: { - if greeters == 0 { - return Optional<[Greeter]>.none - } else { - return [Greeter].bridgeJSLiftParameter() - } - }()) - let __bjs_isSome_ret = ret != nil - if let __bjs_unwrapped_ret = ret { - __bjs_unwrapped_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) + let ret = roundTripOptionalGreeterArrayType(_: Optional<[Greeter]>.bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -9006,9 +8906,9 @@ fileprivate func _bjs_OptionalPropertyHolder_wrap(_ pointer: UnsafeMutableRawPoi @_expose(wasm, "bjs_Container_init") @_cdecl("bjs_Container_init") -public func _bjs_Container_init(_ config: Int32) -> UnsafeMutableRawPointer { +public func _bjs_Container_init() -> UnsafeMutableRawPointer { #if arch(wasm32) - let _tmp_config = Optional.bridgeJSLiftParameter(config) + let _tmp_config = Optional.bridgeJSLiftParameter() let _tmp_location = DataPoint.bridgeJSLiftParameter() let ret = Container(location: _tmp_location, config: _tmp_config) return ret.bridgeJSLowerReturn() @@ -9051,9 +8951,9 @@ public func _bjs_Container_config_get(_ _self: UnsafeMutableRawPointer) -> Void @_expose(wasm, "bjs_Container_config_set") @_cdecl("bjs_Container_config_set") -public func _bjs_Container_config_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { +public func _bjs_Container_config_set(_ _self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - Container.bridgeJSLiftParameter(_self).config = Optional.bridgeJSLiftParameter(value) + Container.bridgeJSLiftParameter(_self).config = Optional.bridgeJSLiftParameter() #else fatalError("Only available on WebAssembly") #endif From 38af37b56002e9185834905f4494b34da25518f2 Mon Sep 17 00:00:00 2001 From: Krzysztof Rodak Date: Wed, 11 Feb 2026 21:12:39 +0100 Subject: [PATCH 29/40] BridgeJS: Delegate nested container codegen to generic runtime conformances --- Benchmarks/Sources/Generated/BridgeJS.swift | 64 ++-------- .../Sources/BridgeJSCore/ExportSwift.swift | 40 +++---- .../BridgeJSCodegenTests/ArrayTypes.swift | 80 ++----------- .../Generated/BridgeJS.swift | 112 +++--------------- 4 files changed, 48 insertions(+), 248 deletions(-) diff --git a/Benchmarks/Sources/Generated/BridgeJS.swift b/Benchmarks/Sources/Generated/BridgeJS.swift index 515d3a531..da7d155e1 100644 --- a/Benchmarks/Sources/Generated/BridgeJS.swift +++ b/Benchmarks/Sources/Generated/BridgeJS.swift @@ -1565,16 +1565,7 @@ public func _bjs_ArrayRoundtrip_makePointArrayLarge(_ _self: UnsafeMutableRawPoi @_cdecl("bjs_ArrayRoundtrip_takeNestedIntArray") public func _bjs_ArrayRoundtrip_takeNestedIntArray(_ _self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - ArrayRoundtrip.bridgeJSLiftParameter(_self).takeNestedIntArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [[Int]] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append([Int].bridgeJSLiftParameter()) - } - __result.reverse() - return __result - }()) + ArrayRoundtrip.bridgeJSLiftParameter(_self).takeNestedIntArray(_: [[Int]].bridgeJSLiftParameter()) #else fatalError("Only available on WebAssembly") #endif @@ -1585,10 +1576,7 @@ public func _bjs_ArrayRoundtrip_takeNestedIntArray(_ _self: UnsafeMutableRawPoin public func _bjs_ArrayRoundtrip_makeNestedIntArray(_ _self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeNestedIntArray() - for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(Int32(ret.count)) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1598,20 +1586,8 @@ public func _bjs_ArrayRoundtrip_makeNestedIntArray(_ _self: UnsafeMutableRawPoin @_cdecl("bjs_ArrayRoundtrip_roundtripNestedIntArray") public func _bjs_ArrayRoundtrip_roundtripNestedIntArray(_ _self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).roundtripNestedIntArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [[Int]] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append([Int].bridgeJSLiftParameter()) - } - __result.reverse() - return __result - }()) - for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(Int32(ret.count)) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).roundtripNestedIntArray(_: [[Int]].bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1621,16 +1597,7 @@ public func _bjs_ArrayRoundtrip_roundtripNestedIntArray(_ _self: UnsafeMutableRa @_cdecl("bjs_ArrayRoundtrip_takeNestedPointArray") public func _bjs_ArrayRoundtrip_takeNestedPointArray(_ _self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - ArrayRoundtrip.bridgeJSLiftParameter(_self).takeNestedPointArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [[Point]] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append([Point].bridgeJSLiftParameter()) - } - __result.reverse() - return __result - }()) + ArrayRoundtrip.bridgeJSLiftParameter(_self).takeNestedPointArray(_: [[Point]].bridgeJSLiftParameter()) #else fatalError("Only available on WebAssembly") #endif @@ -1641,10 +1608,7 @@ public func _bjs_ArrayRoundtrip_takeNestedPointArray(_ _self: UnsafeMutableRawPo public func _bjs_ArrayRoundtrip_makeNestedPointArray(_ _self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeNestedPointArray() - for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(Int32(ret.count)) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -1654,20 +1618,8 @@ public func _bjs_ArrayRoundtrip_makeNestedPointArray(_ _self: UnsafeMutableRawPo @_cdecl("bjs_ArrayRoundtrip_roundtripNestedPointArray") public func _bjs_ArrayRoundtrip_roundtripNestedPointArray(_ _self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).roundtripNestedPointArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [[Point]] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append([Point].bridgeJSLiftParameter()) - } - __result.reverse() - return __result - }()) - for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(Int32(ret.count)) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).roundtripNestedPointArray(_: [[Point]].bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index 2d31cd212..ca9689607 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -838,18 +838,16 @@ struct StackCodegen { func liftArrayExpression(elementType: BridgeType) -> ExprSyntax { switch elementType { - case .int, .uint, .float, .double, .string, .bool, .jsValue, - .jsObject(nil), .swiftStruct, .caseEnum, .swiftHeapObject, - .unsafePointer, .rawValueEnum, .associatedValueEnum: - return "[\(raw: elementType.swiftType)].bridgeJSLiftParameter()" - case .jsObject(_?): + case .jsObject(let className?) where className != "JSObject": return liftArrayExpressionInline(elementType: elementType) case .swiftProtocol(let protocolName): return "[Any\(raw: protocolName)].bridgeJSLiftParameter()" - case .nullable, .array, .closure, .dictionary: + case .nullable, .closure: return liftArrayExpressionInline(elementType: elementType) case .void, .namespaceEnum: fatalError("Invalid array element type: \(elementType)") + default: + return "[\(raw: elementType.swiftType)].bridgeJSLiftParameter()" } } @@ -872,11 +870,7 @@ struct StackCodegen { func liftDictionaryExpression(valueType: BridgeType) -> ExprSyntax { switch valueType { - case .int, .uint, .float, .double, .string, .bool, .jsValue, - .jsObject(nil), .swiftStruct, .caseEnum, .swiftHeapObject, - .unsafePointer, .rawValueEnum, .associatedValueEnum: - return "[String: \(raw: valueType.swiftType)].bridgeJSLiftParameter()" - case .jsObject(let className?): + case .jsObject(let className?) where className != "JSObject": return """ { let __dict = [String: JSObject].bridgeJSLiftParameter() @@ -890,10 +884,12 @@ struct StackCodegen { return __dict.mapValues { $0 as! Any\(raw: protocolName) } }() """ - case .nullable, .array, .dictionary, .closure: + case .nullable, .closure: return liftDictionaryExpressionInline(valueType: valueType) case .void, .namespaceEnum: fatalError("Invalid dictionary value type: \(valueType)") + default: + return "[String: \(raw: valueType.swiftType)].bridgeJSLiftParameter()" } } @@ -1005,15 +1001,11 @@ struct StackCodegen { varPrefix: String ) -> [CodeBlockItemSyntax] { switch elementType { - case .int, .uint, .float, .double, .string, .bool, .jsValue, - .jsObject(nil), .swiftStruct, .caseEnum, .swiftHeapObject, - .unsafePointer, .rawValueEnum, .associatedValueEnum: - return ["\(raw: accessor).bridgeJSLowerReturn()"] - case .jsObject(_?): + case .jsObject(let className?) where className != "JSObject": return ["\(raw: accessor).map { $0.jsObject }.bridgeJSLowerReturn()"] case .swiftProtocol(let protocolName): return ["\(raw: accessor).map { $0 as! Any\(raw: protocolName) }.bridgeJSLowerReturn()"] - case .nullable, .array, .closure, .dictionary: + case .nullable, .closure: return lowerArrayStatementsInline( elementType: elementType, accessor: accessor, @@ -1021,6 +1013,8 @@ struct StackCodegen { ) case .void, .namespaceEnum: fatalError("Invalid array element type: \(elementType)") + default: + return ["\(raw: accessor).bridgeJSLowerReturn()"] } } @@ -1054,15 +1048,11 @@ struct StackCodegen { varPrefix: String ) -> [CodeBlockItemSyntax] { switch valueType { - case .int, .uint, .float, .double, .string, .bool, .jsValue, - .jsObject(nil), .swiftStruct, .caseEnum, .swiftHeapObject, - .unsafePointer, .rawValueEnum, .associatedValueEnum: - return ["\(raw: accessor).bridgeJSLowerReturn()"] - case .jsObject(_?): + case .jsObject(let className?) where className != "JSObject": return ["\(raw: accessor).mapValues { $0.jsObject }.bridgeJSLowerReturn()"] case .swiftProtocol(let protocolName): return ["\(raw: accessor).mapValues { $0 as! Any\(raw: protocolName) }.bridgeJSLowerReturn()"] - case .nullable, .array, .dictionary, .closure: + case .nullable, .closure: return lowerDictionaryStatementsInline( valueType: valueType, accessor: accessor, @@ -1070,6 +1060,8 @@ struct StackCodegen { ) case .void, .namespaceEnum: fatalError("Invalid dictionary value type: \(valueType)") + default: + return ["\(raw: accessor).bridgeJSLowerReturn()"] } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift index 261c0b066..6b10c0fe7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift @@ -381,20 +381,8 @@ public func _bjs_processOptionalStatusArray() -> Void { @_cdecl("bjs_processNestedIntArray") public func _bjs_processNestedIntArray() -> Void { #if arch(wasm32) - let ret = processNestedIntArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [[Int]] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append([Int].bridgeJSLiftParameter()) - } - __result.reverse() - return __result - }()) - for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(Int32(ret.count)) + let ret = processNestedIntArray(_: [[Int]].bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -404,20 +392,8 @@ public func _bjs_processNestedIntArray() -> Void { @_cdecl("bjs_processNestedStringArray") public func _bjs_processNestedStringArray() -> Void { #if arch(wasm32) - let ret = processNestedStringArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [[String]] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append([String].bridgeJSLiftParameter()) - } - __result.reverse() - return __result - }()) - for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(Int32(ret.count)) + let ret = processNestedStringArray(_: [[String]].bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -427,20 +403,8 @@ public func _bjs_processNestedStringArray() -> Void { @_cdecl("bjs_processNestedPointArray") public func _bjs_processNestedPointArray() -> Void { #if arch(wasm32) - let ret = processNestedPointArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [[Point]] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append([Point].bridgeJSLiftParameter()) - } - __result.reverse() - return __result - }()) - for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(Int32(ret.count)) + let ret = processNestedPointArray(_: [[Point]].bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -461,20 +425,8 @@ public func _bjs_processItemArray() -> Void { @_cdecl("bjs_processNestedItemArray") public func _bjs_processNestedItemArray() -> Void { #if arch(wasm32) - let ret = processNestedItemArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [[Item]] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append([Item].bridgeJSLiftParameter()) - } - __result.reverse() - return __result - }()) - for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(Int32(ret.count)) + let ret = processNestedItemArray(_: [[Item]].bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -522,20 +474,8 @@ public func _bjs_processOptionalJSObjectArray() -> Void { @_cdecl("bjs_processNestedJSObjectArray") public func _bjs_processNestedJSObjectArray() -> Void { #if arch(wasm32) - let ret = processNestedJSObjectArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [[JSObject]] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append([JSObject].bridgeJSLiftParameter()) - } - __result.reverse() - return __result - }()) - for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(Int32(ret.count)) + let ret = processNestedJSObjectArray(_: [[JSObject]].bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index af9f15dbc..c37bce3c9 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -5784,20 +5784,8 @@ public func _bjs_roundTripOptionalGreeterArrayType(_ greeters: Int32) -> Void { @_cdecl("bjs_roundTripNestedIntArray") public func _bjs_roundTripNestedIntArray() -> Void { #if arch(wasm32) - let ret = roundTripNestedIntArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [[Int]] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append([Int].bridgeJSLiftParameter()) - } - __result.reverse() - return __result - }()) - for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(Int32(ret.count)) + let ret = roundTripNestedIntArray(_: [[Int]].bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -5807,20 +5795,8 @@ public func _bjs_roundTripNestedIntArray() -> Void { @_cdecl("bjs_roundTripNestedStringArray") public func _bjs_roundTripNestedStringArray() -> Void { #if arch(wasm32) - let ret = roundTripNestedStringArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [[String]] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append([String].bridgeJSLiftParameter()) - } - __result.reverse() - return __result - }()) - for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(Int32(ret.count)) + let ret = roundTripNestedStringArray(_: [[String]].bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -5830,20 +5806,8 @@ public func _bjs_roundTripNestedStringArray() -> Void { @_cdecl("bjs_roundTripNestedDoubleArray") public func _bjs_roundTripNestedDoubleArray() -> Void { #if arch(wasm32) - let ret = roundTripNestedDoubleArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [[Double]] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append([Double].bridgeJSLiftParameter()) - } - __result.reverse() - return __result - }()) - for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(Int32(ret.count)) + let ret = roundTripNestedDoubleArray(_: [[Double]].bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -5853,20 +5817,8 @@ public func _bjs_roundTripNestedDoubleArray() -> Void { @_cdecl("bjs_roundTripNestedBoolArray") public func _bjs_roundTripNestedBoolArray() -> Void { #if arch(wasm32) - let ret = roundTripNestedBoolArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [[Bool]] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append([Bool].bridgeJSLiftParameter()) - } - __result.reverse() - return __result - }()) - for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(Int32(ret.count)) + let ret = roundTripNestedBoolArray(_: [[Bool]].bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -5876,20 +5828,8 @@ public func _bjs_roundTripNestedBoolArray() -> Void { @_cdecl("bjs_roundTripNestedDataPointArray") public func _bjs_roundTripNestedDataPointArray() -> Void { #if arch(wasm32) - let ret = roundTripNestedDataPointArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [[DataPoint]] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append([DataPoint].bridgeJSLiftParameter()) - } - __result.reverse() - return __result - }()) - for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(Int32(ret.count)) + let ret = roundTripNestedDataPointArray(_: [[DataPoint]].bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -5899,20 +5839,8 @@ public func _bjs_roundTripNestedDataPointArray() -> Void { @_cdecl("bjs_roundTripNestedDirectionArray") public func _bjs_roundTripNestedDirectionArray() -> Void { #if arch(wasm32) - let ret = roundTripNestedDirectionArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [[Direction]] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append([Direction].bridgeJSLiftParameter()) - } - __result.reverse() - return __result - }()) - for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(Int32(ret.count)) + let ret = roundTripNestedDirectionArray(_: [[Direction]].bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif @@ -5922,20 +5850,8 @@ public func _bjs_roundTripNestedDirectionArray() -> Void { @_cdecl("bjs_roundTripNestedGreeterArray") public func _bjs_roundTripNestedGreeterArray() -> Void { #if arch(wasm32) - let ret = roundTripNestedGreeterArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [[Greeter]] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append([Greeter].bridgeJSLiftParameter()) - } - __result.reverse() - return __result - }()) - for __bjs_elem_ret in ret { - __bjs_elem_ret.bridgeJSLowerReturn() - } - _swift_js_push_i32(Int32(ret.count)) + let ret = roundTripNestedGreeterArray(_: [[Greeter]].bridgeJSLiftParameter()) + ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif From 6716dfc931fa826fe0c7c8163759157453f2ec59 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Thu, 12 Feb 2026 14:10:53 +0900 Subject: [PATCH 30/40] [NFC] BridgeJS: Remove tag stack and use i32 stack for enum case tags --- Benchmarks/Sources/Generated/BridgeJS.swift | 26 +++--- .../Sources/BridgeJSCore/ExportSwift.swift | 4 +- .../Sources/BridgeJSLink/BridgeJSLink.swift | 6 -- .../Sources/BridgeJSLink/JSGlueGen.swift | 13 +-- .../EnumAssociatedValue.swift | 74 ++++++++--------- .../BridgeJSCodegenTests/Protocol.swift | 4 +- .../StaticFunctions.Global.swift | 4 +- .../StaticFunctions.swift | 4 +- .../BridgeJSCodegenTests/SwiftClosure.swift | 12 +-- .../BridgeJSLinkTests/ArrayTypes.js | 4 - .../__Snapshots__/BridgeJSLinkTests/Async.js | 4 - .../BridgeJSLinkTests/DefaultParameters.js | 4 - .../BridgeJSLinkTests/DictionaryTypes.js | 4 - .../BridgeJSLinkTests/EnumAssociatedValue.js | 38 ++++----- .../BridgeJSLinkTests/EnumCase.js | 4 - .../BridgeJSLinkTests/EnumNamespace.Global.js | 4 - .../BridgeJSLinkTests/EnumNamespace.js | 4 - .../BridgeJSLinkTests/EnumRawType.js | 4 - .../BridgeJSLinkTests/GlobalGetter.js | 4 - .../BridgeJSLinkTests/GlobalThisImports.js | 4 - .../BridgeJSLinkTests/ImportArray.js | 4 - .../ImportedTypeInExportedInterface.js | 4 - .../BridgeJSLinkTests/InvalidPropertyNames.js | 4 - .../BridgeJSLinkTests/JSClass.js | 4 - .../JSClassStaticFunctions.js | 4 - .../BridgeJSLinkTests/JSValue.js | 4 - .../BridgeJSLinkTests/MixedGlobal.js | 4 - .../BridgeJSLinkTests/MixedModules.js | 4 - .../BridgeJSLinkTests/MixedPrivate.js | 4 - .../BridgeJSLinkTests/Namespaces.Global.js | 4 - .../BridgeJSLinkTests/Namespaces.js | 4 - .../BridgeJSLinkTests/Optionals.js | 4 - .../BridgeJSLinkTests/PrimitiveParameters.js | 4 - .../BridgeJSLinkTests/PrimitiveReturn.js | 4 - .../BridgeJSLinkTests/PropertyTypes.js | 4 - .../BridgeJSLinkTests/Protocol.js | 4 - .../StaticFunctions.Global.js | 6 +- .../BridgeJSLinkTests/StaticFunctions.js | 6 +- .../StaticProperties.Global.js | 4 - .../BridgeJSLinkTests/StaticProperties.js | 4 - .../BridgeJSLinkTests/StringParameter.js | 4 - .../BridgeJSLinkTests/StringReturn.js | 4 - .../BridgeJSLinkTests/SwiftClass.js | 4 - .../BridgeJSLinkTests/SwiftClosure.js | 8 +- .../BridgeJSLinkTests/SwiftClosureImports.js | 4 - .../BridgeJSLinkTests/SwiftStruct.js | 4 - .../BridgeJSLinkTests/SwiftStructImports.js | 4 - .../__Snapshots__/BridgeJSLinkTests/Throws.js | 4 - .../BridgeJSLinkTests/UnsafePointer.js | 4 - .../VoidParameterVoidReturn.js | 4 - Plugins/PackageToJS/Templates/instantiate.js | 1 - .../JavaScriptKit/BridgeJSIntrinsics.swift | 11 +-- .../Generated/BridgeJS.swift | 80 +++++++++---------- 53 files changed, 130 insertions(+), 315 deletions(-) diff --git a/Benchmarks/Sources/Generated/BridgeJS.swift b/Benchmarks/Sources/Generated/BridgeJS.swift index fe655a96f..cdd3aa775 100644 --- a/Benchmarks/Sources/Generated/BridgeJS.swift +++ b/Benchmarks/Sources/Generated/BridgeJS.swift @@ -65,21 +65,21 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .failure(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .flag(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) case .rate(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(3)) + _swift_js_push_i32(Int32(3)) case .precise(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(4)) + _swift_js_push_i32(Int32(4)) case .info: - _swift_js_push_tag(Int32(5)) + _swift_js_push_i32(Int32(5)) } } } @@ -162,26 +162,26 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .error(let param0, let param1): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .location(let param0, let param1, let param2): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() param2.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) case .status(let param0, let param1, let param2): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() param2.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(3)) + _swift_js_push_i32(Int32(3)) case .coordinates(let param0, let param1, let param2): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() param2.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(4)) + _swift_js_push_i32(Int32(4)) case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() @@ -192,9 +192,9 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { param6.bridgeJSLowerStackReturn() param7.bridgeJSLowerStackReturn() param8.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(5)) + _swift_js_push_i32(Int32(5)) case .info: - _swift_js_push_tag(Int32(6)) + _swift_js_push_i32(Int32(6)) } } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index d44e9afbf..304ded82b 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -1323,7 +1323,7 @@ struct EnumCodegen { if enumCase.associatedValues.isEmpty { printer.write("case .\(enumCase.name):") printer.indent { - printer.write("_swift_js_push_tag(Int32(\(caseIndex)))") + printer.write("_swift_js_push_i32(Int32(\(caseIndex)))") } } else { let pattern = enumCase.associatedValues.enumerated() @@ -1334,7 +1334,7 @@ struct EnumCodegen { generatePayloadPushingCode(printer: printer, associatedValues: enumCase.associatedValues) // Push tag AFTER payloads so it's popped first (LIFO) by the JS lift function. // This ensures nested enum tags don't overwrite the outer tag. - printer.write("_swift_js_push_tag(Int32(\(caseIndex)))") + printer.write("_swift_js_push_i32(Int32(\(caseIndex)))") } } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index af5c94276..44b6f0c38 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -246,7 +246,6 @@ public struct BridgeJSLink { "let \(JSGlueVariableScope.reservedStorageToReturnOptionalFloat);", "let \(JSGlueVariableScope.reservedStorageToReturnOptionalDouble);", "let \(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject);", - "let \(JSGlueVariableScope.reservedTagStack) = [];", "let \(JSGlueVariableScope.reservedStringStack) = [];", "let \(JSGlueVariableScope.reservedI32Stack) = [];", "let \(JSGlueVariableScope.reservedF32Stack) = [];", @@ -342,11 +341,6 @@ public struct BridgeJSLink { printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(id);") } printer.write("}") - printer.write("bjs[\"swift_js_push_tag\"] = function(tag) {") - printer.indent { - printer.write("\(JSGlueVariableScope.reservedTagStack).push(tag);") - } - printer.write("}") printer.write("bjs[\"swift_js_push_i32\"] = function(v) {") printer.indent { printer.write("\(JSGlueVariableScope.reservedI32Stack).push(v | 0);") diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 1e384d833..36d463ab4 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -23,7 +23,6 @@ final class JSGlueVariableScope { static let reservedStorageToReturnOptionalHeapObject = "tmpRetOptionalHeapObject" static let reservedTextEncoder = "textEncoder" static let reservedTextDecoder = "textDecoder" - static let reservedTagStack = "tagStack" static let reservedStringStack = "strStack" static let reservedI32Stack = "i32Stack" static let reservedF32Stack = "f32Stack" @@ -52,7 +51,6 @@ final class JSGlueVariableScope { reservedStorageToReturnOptionalHeapObject, reservedTextEncoder, reservedTextDecoder, - reservedTagStack, reservedStringStack, reservedI32Stack, reservedF32Stack, @@ -122,9 +120,6 @@ extension JSGlueVariableScope { func emitPushPointerReturn(_ value: String, printer: CodeFragmentPrinter) { printer.write("\(JSGlueVariableScope.reservedPointerStack).push(\(value));") } - func popTag() -> String { - return "\(JSGlueVariableScope.reservedTagStack).pop()" - } func popString() -> String { return "\(JSGlueVariableScope.reservedStringStack).pop()" } @@ -661,7 +656,7 @@ struct IntrinsicJSFragment: Sendable { let (scope, printer) = (context.scope, context.printer) let retName = scope.variable("ret") printer.write( - "const \(retName) = \(JSGlueVariableScope.reservedEnumHelpers).\(enumBase).lift(\(scope.popTag()));" + "const \(retName) = \(JSGlueVariableScope.reservedEnumHelpers).\(enumBase).lift(\(scope.popI32()));" ) return [retName] } @@ -1022,7 +1017,7 @@ struct IntrinsicJSFragment: Sendable { case .associatedValueEnum(let fullName): let base = fullName.components(separatedBy: ".").last ?? fullName let tagVar = scope.variable("tag") - printer.write("const \(tagVar) = \(scope.popTag());") + printer.write("const \(tagVar) = \(scope.popI32());") let isNullVar = scope.variable("isNull") printer.write("const \(isNullVar) = (\(tagVar) === -1);") printer.write("let \(resultVar);") @@ -2112,7 +2107,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("if (\(isSomeVar)) {") try printer.indent { // For optional associated value enums, Swift uses bridgeJSLowerParameter() - // which pushes caseId to i32Stack (not tagStack like bridgeJSLowerReturn()). + // which pushes caseId to i32Stack (same as bridgeJSLowerReturn()). if case .associatedValueEnum(let fullName) = wrappedType { let base = fullName.components(separatedBy: ".").last ?? fullName let caseIdVar = scope.variable("caseId") @@ -2486,7 +2481,7 @@ struct IntrinsicJSFragment: Sendable { let (scope, printer) = (context.scope, context.printer) let resultVar = scope.variable("enumValue") printer.write( - "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(scope.popTag()), );" + "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(scope.popI32()), );" ) return [resultVar] } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift index a21c766c0..9787865f2 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift @@ -56,21 +56,21 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .failure(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .flag(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) case .rate(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(3)) + _swift_js_push_i32(Int32(3)) case .precise(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(4)) + _swift_js_push_i32(Int32(4)) case .info: - _swift_js_push_tag(Int32(5)) + _swift_js_push_i32(Int32(5)) } } } @@ -146,21 +146,21 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .error(let param0, let param1): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .status(let param0, let param1, let param2): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() param2.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) case .coordinates(let param0, let param1, let param2): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() param2.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(3)) + _swift_js_push_i32(Int32(3)) case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() @@ -171,9 +171,9 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { param6.bridgeJSLowerStackReturn() param7.bridgeJSLowerStackReturn() param8.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(4)) + _swift_js_push_i32(Int32(4)) case .info: - _swift_js_push_tag(Int32(5)) + _swift_js_push_i32(Int32(5)) } } } @@ -225,16 +225,16 @@ extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .failure(let param0, let param1): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .status(let param0, let param1, let param2): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() param2.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) } } } @@ -279,11 +279,11 @@ extension NetworkingResult: _BridgedSwiftAssociatedValueEnum { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .failure(let param0, let param1): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) } } } @@ -363,7 +363,7 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .failure(let param0, let param1): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { @@ -375,7 +375,7 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { __bjs_unwrapped_param1.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .status(let param0, let param1, let param2): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { @@ -392,7 +392,7 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { __bjs_unwrapped_param2.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param2 ? 1 : 0) - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) } } } @@ -504,26 +504,26 @@ extension TypedPayloadResult: _BridgedSwiftAssociatedValueEnum { switch self { case .precision(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .direction(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .optPrecision(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) case .optDirection(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_tag(Int32(3)) + _swift_js_push_i32(Int32(3)) case .empty: - _swift_js_push_tag(Int32(4)) + _swift_js_push_i32(Int32(4)) } } } @@ -586,21 +586,21 @@ extension AllTypesResult: _BridgedSwiftAssociatedValueEnum { switch self { case .structPayload(let param0): param0.bridgeJSLowerReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .classPayload(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .jsObjectPayload(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) case .nestedEnum(let param0): param0.bridgeJSLowerReturn() - _swift_js_push_tag(Int32(3)) + _swift_js_push_i32(Int32(3)) case .arrayPayload(let param0): param0.bridgeJSLowerReturn() - _swift_js_push_tag(Int32(4)) + _swift_js_push_i32(Int32(4)) case .empty: - _swift_js_push_tag(Int32(5)) + _swift_js_push_i32(Int32(5)) } } } @@ -675,33 +675,33 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { switch self { case .optStruct(let param0): param0.bridgeJSLowerReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .optClass(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .optJSObject(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) case .optNestedEnum(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { _swift_js_push_i32(__bjs_unwrapped_param0.bridgeJSLowerParameter()) } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_tag(Int32(3)) + _swift_js_push_i32(Int32(3)) case .optArray(let param0): param0.bridgeJSLowerReturn() - _swift_js_push_tag(Int32(4)) + _swift_js_push_i32(Int32(4)) case .empty: - _swift_js_push_tag(Int32(5)) + _swift_js_push_i32(Int32(5)) } } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift index 55521dbaf..9b68b96ed 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift @@ -401,10 +401,10 @@ extension Result: _BridgedSwiftAssociatedValueEnum { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .failure(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) } } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.Global.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.Global.swift index 3e5b40def..a7b0578a9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.Global.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.Global.swift @@ -83,10 +83,10 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .failure(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) } } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.swift index 3e5b40def..a7b0578a9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.swift @@ -83,10 +83,10 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .failure(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) } } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift index 8aa9efd65..d8b3c9bb8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift @@ -1245,21 +1245,21 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .failure(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .flag(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) case .rate(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(3)) + _swift_js_push_i32(Int32(3)) case .precise(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(4)) + _swift_js_push_i32(Int32(4)) case .info: - _swift_js_push_tag(Int32(5)) + _swift_js_push_i32(Int32(5)) } } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js index a381f5569..97531d378 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js @@ -31,7 +31,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -93,9 +92,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js index 0f4dce413..b215b3691 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -65,9 +64,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js index 04335c58c..fba9f9c6b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js @@ -24,7 +24,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -118,9 +117,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js index a77407eca..1f7fe91e1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -66,9 +65,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js index 18c6999c1..3a4818463 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js @@ -99,7 +99,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -698,7 +697,7 @@ export async function createInstantiator(options, swift) { return { tag: AllTypesResultValues.Tag.JsObjectPayload, param0: obj }; } case AllTypesResultValues.Tag.NestedEnum: { - const enumValue = enumHelpers.APIResult.lift(tagStack.pop(), ); + const enumValue = enumHelpers.APIResult.lift(i32Stack.pop(), ); return { tag: AllTypesResultValues.Tag.NestedEnum, param0: enumValue }; } case AllTypesResultValues.Tag.ArrayPayload: { @@ -911,9 +910,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } @@ -1136,13 +1132,13 @@ export async function createInstantiator(options, swift) { }, getResult: function bjs_getResult() { instance.exports.bjs_getResult(); - const ret = enumHelpers.APIResult.lift(tagStack.pop()); + const ret = enumHelpers.APIResult.lift(i32Stack.pop()); return ret; }, roundtripAPIResult: function bjs_roundtripAPIResult(result) { const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.APIResult.lower(result); instance.exports.bjs_roundtripAPIResult(resultCaseId); - const ret = enumHelpers.APIResult.lift(tagStack.pop()); + const ret = enumHelpers.APIResult.lift(i32Stack.pop()); if (resultCleanup) { resultCleanup(); } return ret; }, @@ -1155,7 +1151,7 @@ export async function createInstantiator(options, swift) { resultCleanup = enumResult.cleanup; } instance.exports.bjs_roundTripOptionalAPIResult(+isSome, isSome ? resultCaseId : 0); - const tag = tagStack.pop(); + const tag = i32Stack.pop(); const isNull = (tag === -1); let optResult; if (isNull) { @@ -1173,13 +1169,13 @@ export async function createInstantiator(options, swift) { }, getComplexResult: function bjs_getComplexResult() { instance.exports.bjs_getComplexResult(); - const ret = enumHelpers.ComplexResult.lift(tagStack.pop()); + const ret = enumHelpers.ComplexResult.lift(i32Stack.pop()); return ret; }, roundtripComplexResult: function bjs_roundtripComplexResult(result) { const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.ComplexResult.lower(result); instance.exports.bjs_roundtripComplexResult(resultCaseId); - const ret = enumHelpers.ComplexResult.lift(tagStack.pop()); + const ret = enumHelpers.ComplexResult.lift(i32Stack.pop()); if (resultCleanup) { resultCleanup(); } return ret; }, @@ -1192,7 +1188,7 @@ export async function createInstantiator(options, swift) { resultCleanup = enumResult.cleanup; } instance.exports.bjs_roundTripOptionalComplexResult(+isSome, isSome ? resultCaseId : 0); - const tag = tagStack.pop(); + const tag = i32Stack.pop(); const isNull = (tag === -1); let optResult; if (isNull) { @@ -1212,7 +1208,7 @@ export async function createInstantiator(options, swift) { resultCleanup = enumResult.cleanup; } instance.exports.bjs_roundTripOptionalUtilitiesResult(+isSome, isSome ? resultCaseId : 0); - const tag = tagStack.pop(); + const tag = i32Stack.pop(); const isNull = (tag === -1); let optResult; if (isNull) { @@ -1232,7 +1228,7 @@ export async function createInstantiator(options, swift) { resultCleanup = enumResult.cleanup; } instance.exports.bjs_roundTripOptionalNetworkingResult(+isSome, isSome ? resultCaseId : 0); - const tag = tagStack.pop(); + const tag = i32Stack.pop(); const isNull = (tag === -1); let optResult; if (isNull) { @@ -1252,7 +1248,7 @@ export async function createInstantiator(options, swift) { resultCleanup = enumResult.cleanup; } instance.exports.bjs_roundTripOptionalAPIOptionalResult(+isSome, isSome ? resultCaseId : 0); - const tag = tagStack.pop(); + const tag = i32Stack.pop(); const isNull = (tag === -1); let optResult; if (isNull) { @@ -1279,7 +1275,7 @@ export async function createInstantiator(options, swift) { result2Cleanup = enumResult1.cleanup; } instance.exports.bjs_compareAPIResults(+isSome, isSome ? result1CaseId : 0, +isSome1, isSome1 ? result2CaseId : 0); - const tag = tagStack.pop(); + const tag = i32Stack.pop(); const isNull = (tag === -1); let optResult; if (isNull) { @@ -1294,7 +1290,7 @@ export async function createInstantiator(options, swift) { roundTripTypedPayloadResult: function bjs_roundTripTypedPayloadResult(result) { const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.TypedPayloadResult.lower(result); instance.exports.bjs_roundTripTypedPayloadResult(resultCaseId); - const ret = enumHelpers.TypedPayloadResult.lift(tagStack.pop()); + const ret = enumHelpers.TypedPayloadResult.lift(i32Stack.pop()); if (resultCleanup) { resultCleanup(); } return ret; }, @@ -1307,7 +1303,7 @@ export async function createInstantiator(options, swift) { resultCleanup = enumResult.cleanup; } instance.exports.bjs_roundTripOptionalTypedPayloadResult(+isSome, isSome ? resultCaseId : 0); - const tag = tagStack.pop(); + const tag = i32Stack.pop(); const isNull = (tag === -1); let optResult; if (isNull) { @@ -1321,7 +1317,7 @@ export async function createInstantiator(options, swift) { roundTripAllTypesResult: function bjs_roundTripAllTypesResult(result) { const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.AllTypesResult.lower(result); instance.exports.bjs_roundTripAllTypesResult(resultCaseId); - const ret = enumHelpers.AllTypesResult.lift(tagStack.pop()); + const ret = enumHelpers.AllTypesResult.lift(i32Stack.pop()); if (resultCleanup) { resultCleanup(); } return ret; }, @@ -1334,7 +1330,7 @@ export async function createInstantiator(options, swift) { resultCleanup = enumResult.cleanup; } instance.exports.bjs_roundTripOptionalAllTypesResult(+isSome, isSome ? resultCaseId : 0); - const tag = tagStack.pop(); + const tag = i32Stack.pop(); const isNull = (tag === -1); let optResult; if (isNull) { @@ -1348,7 +1344,7 @@ export async function createInstantiator(options, swift) { roundTripOptionalPayloadResult: function bjs_roundTripOptionalPayloadResult(result) { const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.OptionalAllTypesResult.lower(result); instance.exports.bjs_roundTripOptionalPayloadResult(resultCaseId); - const ret = enumHelpers.OptionalAllTypesResult.lift(tagStack.pop()); + const ret = enumHelpers.OptionalAllTypesResult.lift(i32Stack.pop()); if (resultCleanup) { resultCleanup(); } return ret; }, @@ -1361,7 +1357,7 @@ export async function createInstantiator(options, swift) { resultCleanup = enumResult.cleanup; } instance.exports.bjs_roundTripOptionalPayloadResultOpt(+isSome, isSome ? resultCaseId : 0); - const tag = tagStack.pop(); + const tag = i32Stack.pop(); const isNull = (tag === -1); let optResult; if (isNull) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js index 6ed445811..341ffb260 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js @@ -42,7 +42,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -89,9 +88,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js index 55f995024..fa4586a2d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js @@ -62,7 +62,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -109,9 +108,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js index 179712fef..5d85347ee 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js @@ -43,7 +43,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -90,9 +89,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js index 0855f11ec..04d667b8e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js @@ -93,7 +93,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -141,9 +140,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js index c9ccf98fe..a60d5377f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -66,9 +65,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js index 947ee4d11..e0b4f8f94 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -65,9 +64,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js index 6c56cce6f..80ff1cead 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -66,9 +65,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js index b0674f388..7e2f48981 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -130,9 +129,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js index 9ac03ee73..3f5d49f35 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -66,9 +65,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js index 6e9100b11..66abcf418 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -66,9 +65,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js index b466d0900..138bef6a1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -66,9 +65,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js index f6e4bf8aa..426fd8c1a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -155,9 +154,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js index 7bb3c14d6..590e84cc3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -65,9 +64,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js index ac2270b9f..18fb5af6c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -65,9 +64,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js index 3205ef5d0..27bad9aea 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -65,9 +64,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js index ed8f6db8b..9e6782d12 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -65,9 +64,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js index c148f0761..94a4b73fb 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -65,9 +64,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js index b69033543..f637af601 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -66,9 +65,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js index 11a199b71..dd59941f7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -66,9 +65,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js index bb1e7ad40..a67637e58 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -66,9 +65,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js index 4e8e86821..35bc1d028 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -65,9 +64,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js index fd37c7178..d783e8968 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js @@ -42,7 +42,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -128,9 +127,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js index fcf19c54f..892110aca 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js @@ -29,7 +29,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -115,9 +114,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } @@ -332,7 +328,7 @@ export async function createInstantiator(options, swift) { roundtrip: function(value) { const { caseId: valueCaseId, cleanup: valueCleanup } = enumHelpers.APIResult.lower(value); instance.exports.bjs_APIResult_static_roundtrip(valueCaseId); - const ret = enumHelpers.APIResult.lift(tagStack.pop()); + const ret = enumHelpers.APIResult.lift(i32Stack.pop()); if (valueCleanup) { valueCleanup(); } return ret; } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js index 5e82061d9..f2c93adae 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js @@ -29,7 +29,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -115,9 +114,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } @@ -326,7 +322,7 @@ export async function createInstantiator(options, swift) { roundtrip: function(value) { const { caseId: valueCaseId, cleanup: valueCleanup } = enumHelpers.APIResult.lower(value); instance.exports.bjs_APIResult_static_roundtrip(valueCaseId); - const ret = enumHelpers.APIResult.lift(tagStack.pop()); + const ret = enumHelpers.APIResult.lift(i32Stack.pop()); if (valueCleanup) { valueCleanup(); } return ret; } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js index ad44e80fa..adb809f6f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -70,9 +69,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js index fb43d426b..f1273821a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -70,9 +69,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js index 1ee9f519e..b81a4990b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -66,9 +65,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js index 02833d1c6..112f853d4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -66,9 +65,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js index 13ea6ba75..fc2fc58c6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -66,9 +65,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js index 2ef9aaf5a..4df3d5018 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js @@ -48,7 +48,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -191,9 +190,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } @@ -419,7 +415,7 @@ export async function createInstantiator(options, swift) { const lower_closure_TestModule_10TestModule9APIResultO_9APIResultO = function(param0) { const { caseId: param0CaseId, cleanup: param0Cleanup } = enumHelpers.APIResult.lower(param0); instance.exports.invoke_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO(boxPtr, param0CaseId); - const ret = enumHelpers.APIResult.lift(tagStack.pop()); + const ret = enumHelpers.APIResult.lift(i32Stack.pop()); if (param0Cleanup) { param0Cleanup(); } if (tmpRetException) { const error = swift.memory.getObject(tmpRetException); @@ -701,7 +697,7 @@ export async function createInstantiator(options, swift) { param0Cleanup = enumResult.cleanup; } instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(boxPtr, +isSome, isSome ? param0CaseId : 0); - const tag = tagStack.pop(); + const tag = i32Stack.pop(); const isNull = (tag === -1); let optResult; if (isNull) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js index 98899d4df..8744f5e45 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -91,9 +90,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js index 3f42f3103..ff8c8f8b0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js @@ -23,7 +23,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -323,9 +322,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js index 751b28959..a33914d89 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -80,9 +79,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js index 50276543c..e81050bf6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -65,9 +64,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js index 29474892f..cdcd6db3a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -85,9 +84,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js index de17f5edc..05a16a3eb 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js @@ -18,7 +18,6 @@ export async function createInstantiator(options, swift) { let tmpRetOptionalFloat; let tmpRetOptionalDouble; let tmpRetOptionalHeapObject; - let tagStack = []; let strStack = []; let i32Stack = []; let f32Stack = []; @@ -66,9 +65,6 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } - bjs["swift_js_push_tag"] = function(tag) { - tagStack.push(tag); - } bjs["swift_js_push_i32"] = function(v) { i32Stack.push(v | 0); } diff --git a/Plugins/PackageToJS/Templates/instantiate.js b/Plugins/PackageToJS/Templates/instantiate.js index a0920964b..955c2928c 100644 --- a/Plugins/PackageToJS/Templates/instantiate.js +++ b/Plugins/PackageToJS/Templates/instantiate.js @@ -39,7 +39,6 @@ async function createInstantiator(options, swift) { swift_js_throw: unexpectedBjsCall, swift_js_retain: unexpectedBjsCall, swift_js_release: unexpectedBjsCall, - swift_js_push_tag: unexpectedBjsCall, swift_js_push_i32: unexpectedBjsCall, swift_js_push_f32: unexpectedBjsCall, swift_js_push_f64: unexpectedBjsCall, diff --git a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift index d1390a610..feca05b3b 100644 --- a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift +++ b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift @@ -694,15 +694,6 @@ where Self: RawRepresentable, RawValue: _BridgedSwiftTypeLoweredIntoSingleWasmCo } #endif -#if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_push_tag") -@_spi(BridgeJS) public func _swift_js_push_tag(_ tag: Int32) -#else -@_spi(BridgeJS) public func _swift_js_push_tag(_ tag: Int32) { - _onlyAvailableOnWasm() -} -#endif - #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_push_string") @_spi(BridgeJS) public func _swift_js_push_string(_ ptr: UnsafePointer?, _ len: Int32) @@ -1963,7 +1954,7 @@ extension Optional where Wrapped: _BridgedSwiftAssociatedValueEnum { @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { switch consume self { case .none: - _swift_js_push_tag(-1) // Use -1 as sentinel for null + _swift_js_push_i32(-1) // Use -1 as sentinel for null case .some(let value): value.bridgeJSLowerReturn() } diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index 90a0dbddf..745c56472 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -2083,21 +2083,21 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .failure(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .flag(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) case .rate(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(3)) + _swift_js_push_i32(Int32(3)) case .precise(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(4)) + _swift_js_push_i32(Int32(4)) case .info: - _swift_js_push_tag(Int32(5)) + _swift_js_push_i32(Int32(5)) } } } @@ -2180,26 +2180,26 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .error(let param0, let param1): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .location(let param0, let param1, let param2): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() param2.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) case .status(let param0, let param1, let param2): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() param2.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(3)) + _swift_js_push_i32(Int32(3)) case .coordinates(let param0, let param1, let param2): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() param2.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(4)) + _swift_js_push_i32(Int32(4)) case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() @@ -2210,9 +2210,9 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { param6.bridgeJSLowerStackReturn() param7.bridgeJSLowerStackReturn() param8.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(5)) + _swift_js_push_i32(Int32(5)) case .info: - _swift_js_push_tag(Int32(6)) + _swift_js_push_i32(Int32(6)) } } } @@ -2264,16 +2264,16 @@ extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .failure(let param0, let param1): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .status(let param0, let param1, let param2): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() param2.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) } } } @@ -2318,11 +2318,11 @@ extension API.NetworkingResult: _BridgedSwiftAssociatedValueEnum { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .failure(let param0, let param1): param0.bridgeJSLowerStackReturn() param1.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) } } } @@ -2390,24 +2390,24 @@ extension AllTypesResult: _BridgedSwiftAssociatedValueEnum { switch self { case .structPayload(let param0): param0.bridgeJSLowerReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .classPayload(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .jsObjectPayload(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) case .nestedEnum(let param0): param0.bridgeJSLowerReturn() - _swift_js_push_tag(Int32(3)) + _swift_js_push_i32(Int32(3)) case .arrayPayload(let param0): param0.bridgeJSLowerReturn() - _swift_js_push_tag(Int32(4)) + _swift_js_push_i32(Int32(4)) case .jsClassPayload(let param0): param0.jsObject.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(5)) + _swift_js_push_i32(Int32(5)) case .empty: - _swift_js_push_tag(Int32(6)) + _swift_js_push_i32(Int32(6)) } } } @@ -2473,26 +2473,26 @@ extension TypedPayloadResult: _BridgedSwiftAssociatedValueEnum { switch self { case .precision(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .direction(let param0): param0.bridgeJSLowerStackReturn() - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .optPrecision(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) case .optDirection(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_tag(Int32(3)) + _swift_js_push_i32(Int32(3)) case .empty: - _swift_js_push_tag(Int32(4)) + _swift_js_push_i32(Int32(4)) } } } @@ -2881,40 +2881,40 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { switch self { case .optStruct(let param0): param0.bridgeJSLowerReturn() - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .optClass(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .optJSObject(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) case .optNestedEnum(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { _swift_js_push_i32(__bjs_unwrapped_param0.bridgeJSLowerParameter()) } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_tag(Int32(3)) + _swift_js_push_i32(Int32(3)) case .optArray(let param0): param0.bridgeJSLowerReturn() - _swift_js_push_tag(Int32(4)) + _swift_js_push_i32(Int32(4)) case .optJsClass(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { __bjs_unwrapped_param0.jsObject.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_tag(Int32(5)) + _swift_js_push_i32(Int32(5)) case .empty: - _swift_js_push_tag(Int32(6)) + _swift_js_push_i32(Int32(6)) } } } @@ -2994,7 +2994,7 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_tag(Int32(0)) + _swift_js_push_i32(Int32(0)) case .failure(let param0, let param1): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { @@ -3006,7 +3006,7 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { __bjs_unwrapped_param1.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) - _swift_js_push_tag(Int32(1)) + _swift_js_push_i32(Int32(1)) case .status(let param0, let param1, let param2): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { @@ -3023,7 +3023,7 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { __bjs_unwrapped_param2.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param2 ? 1 : 0) - _swift_js_push_tag(Int32(2)) + _swift_js_push_i32(Int32(2)) } } } From e129b41a23d407b8b0f77cf1375e13674031b0d9 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Thu, 12 Feb 2026 15:28:49 +0900 Subject: [PATCH 31/40] [NFC] BridgeJS: Minimize enum with assoc values code generation --- Benchmarks/Sources/Generated/BridgeJS.swift | 94 +---- .../Sources/BridgeJSCore/ExportSwift.swift | 63 +--- .../EnumAssociatedValue.swift | 338 +---------------- .../BridgeJSCodegenTests/Protocol.swift | 27 +- .../StaticFunctions.Global.swift | 27 +- .../StaticFunctions.swift | 27 +- .../BridgeJSCodegenTests/SwiftClosure.swift | 38 +- .../JavaScriptKit/BridgeJSIntrinsics.swift | 33 +- .../Generated/BridgeJS.swift | 353 +----------------- 9 files changed, 76 insertions(+), 924 deletions(-) diff --git a/Benchmarks/Sources/Generated/BridgeJS.swift b/Benchmarks/Sources/Generated/BridgeJS.swift index cdd3aa775..9a1b30dc4 100644 --- a/Benchmarks/Sources/Generated/BridgeJS.swift +++ b/Benchmarks/Sources/Generated/BridgeJS.swift @@ -8,7 +8,7 @@ @_spi(BridgeJS) import JavaScriptKit extension APIResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> APIResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> APIResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter()) @@ -27,9 +27,7 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() @@ -50,42 +48,10 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { return Int32(5) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> APIResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> APIResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .success(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(0)) - case .failure(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - case .flag(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(2)) - case .rate(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(3)) - case .precise(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(4)) - case .info: - _swift_js_push_i32(Int32(5)) - } - } } extension ComplexResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> ComplexResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> ComplexResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter()) @@ -106,9 +72,7 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() @@ -147,56 +111,6 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { return Int32(6) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> ComplexResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> ComplexResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .success(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(0)) - case .error(let param0, let param1): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - case .location(let param0, let param1, let param2): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - param2.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(2)) - case .status(let param0, let param1, let param2): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - param2.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(3)) - case .coordinates(let param0, let param1, let param2): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - param2.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(4)) - case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - param2.bridgeJSLowerStackReturn() - param3.bridgeJSLowerStackReturn() - param4.bridgeJSLowerStackReturn() - param5.bridgeJSLowerStackReturn() - param6.bridgeJSLowerStackReturn() - param7.bridgeJSLowerStackReturn() - param8.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(5)) - case .info: - _swift_js_push_i32(Int32(6)) - } - } } extension SimpleStruct: _BridgedSwiftStruct { diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index 304ded82b..5fb6f103f 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -1199,7 +1199,9 @@ struct EnumCodegen { let printer = CodeFragmentPrinter() printer.write("extension \(typeName): _BridgedSwiftAssociatedValueEnum {") printer.indent { - printer.write("private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> \(typeName) {") + printer.write( + "@_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> \(typeName) {" + ) printer.indent { printer.write("switch caseId {") generateStackLiftSwitchCases(printer: printer, enumDef: enumDef) @@ -1212,40 +1214,7 @@ struct EnumCodegen { printer.write("}") printer.nextLine() - printer.write("// MARK: Protocol Export") - printer.nextLine() - - printer.write("@_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 {") - printer.indent { - printer.write("switch self {") - generateLowerParameterSwitchCases(printer: printer, enumDef: enumDef) - printer.write("}") - } - printer.write("}") - printer.nextLine() - - printer.write( - multilineString: """ - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> \(typeName) { - return _bridgeJSLiftFromCaseId(caseId) - } - """ - ) - printer.nextLine() - - printer.write("// MARK: ExportSwift") - printer.nextLine() - - printer.write( - multilineString: """ - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> \(typeName) { - return _bridgeJSLiftFromCaseId(caseId) - } - """ - ) - printer.nextLine() - - printer.write("@_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() {") + printer.write("@_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 {") printer.indent { printer.write("switch self {") generateReturnSwitchCases(printer: printer, enumDef: enumDef) @@ -1298,32 +1267,12 @@ struct EnumCodegen { } } - private func generateLowerParameterSwitchCases(printer: CodeFragmentPrinter, enumDef: ExportedEnum) { - for (caseIndex, enumCase) in enumDef.cases.enumerated() { - if enumCase.associatedValues.isEmpty { - printer.write("case .\(enumCase.name):") - printer.indent { - printer.write("return Int32(\(caseIndex))") - } - } else { - let pattern = enumCase.associatedValues.enumerated() - .map { index, associatedValue in "let \(associatedValue.label ?? "param\(index)")" } - .joined(separator: ", ") - printer.write("case .\(enumCase.name)(\(pattern)):") - printer.indent { - generatePayloadPushingCode(printer: printer, associatedValues: enumCase.associatedValues) - printer.write("return Int32(\(caseIndex))") - } - } - } - } - private func generateReturnSwitchCases(printer: CodeFragmentPrinter, enumDef: ExportedEnum) { for (caseIndex, enumCase) in enumDef.cases.enumerated() { if enumCase.associatedValues.isEmpty { printer.write("case .\(enumCase.name):") printer.indent { - printer.write("_swift_js_push_i32(Int32(\(caseIndex)))") + printer.write("return Int32(\(caseIndex))") } } else { let pattern = enumCase.associatedValues.enumerated() @@ -1334,7 +1283,7 @@ struct EnumCodegen { generatePayloadPushingCode(printer: printer, associatedValues: enumCase.associatedValues) // Push tag AFTER payloads so it's popped first (LIFO) by the JS lift function. // This ensures nested enum tags don't overwrite the outer tag. - printer.write("_swift_js_push_i32(Int32(\(caseIndex)))") + printer.write("return Int32(\(caseIndex))") } } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift index 9787865f2..8705c929e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift @@ -1,5 +1,5 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> APIResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> APIResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter()) @@ -18,9 +18,7 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() @@ -41,42 +39,10 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { return Int32(5) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> APIResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> APIResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .success(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(0)) - case .failure(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - case .flag(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(2)) - case .rate(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(3)) - case .precise(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(4)) - case .info: - _swift_js_push_i32(Int32(5)) - } - } } extension ComplexResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> ComplexResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> ComplexResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter()) @@ -95,9 +61,7 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() @@ -131,55 +95,10 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { return Int32(5) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> ComplexResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> ComplexResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .success(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(0)) - case .error(let param0, let param1): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - case .status(let param0, let param1, let param2): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - param2.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(2)) - case .coordinates(let param0, let param1, let param2): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - param2.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(3)) - case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - param2.bridgeJSLowerStackReturn() - param3.bridgeJSLowerStackReturn() - param4.bridgeJSLowerStackReturn() - param5.bridgeJSLowerStackReturn() - param6.bridgeJSLowerStackReturn() - param7.bridgeJSLowerStackReturn() - param8.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(4)) - case .info: - _swift_js_push_i32(Int32(5)) - } - } } extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> Utilities.Result { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> Utilities.Result { switch caseId { case 0: return .success(String.bridgeJSLiftParameter()) @@ -192,9 +111,7 @@ extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() @@ -210,37 +127,10 @@ extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { return Int32(2) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> Utilities.Result { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> Utilities.Result { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .success(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(0)) - case .failure(let param0, let param1): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - case .status(let param0, let param1, let param2): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - param2.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(2)) - } - } } extension NetworkingResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> NetworkingResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> NetworkingResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter()) @@ -251,9 +141,7 @@ extension NetworkingResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() @@ -264,32 +152,10 @@ extension NetworkingResult: _BridgedSwiftAssociatedValueEnum { return Int32(1) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> NetworkingResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> NetworkingResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .success(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(0)) - case .failure(let param0, let param1): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - } - } } extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> APIOptionalResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> APIOptionalResult { switch caseId { case 0: return .success(Optional.bridgeJSLiftParameter()) @@ -302,9 +168,7 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .success(let param0): let __bjs_isSome_param0 = param0 != nil @@ -344,57 +208,6 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { return Int32(2) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> APIOptionalResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> APIOptionalResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .success(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_i32(Int32(0)) - case .failure(let param0, let param1): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - let __bjs_isSome_param1 = param1 != nil - if let __bjs_unwrapped_param1 = param1 { - __bjs_unwrapped_param1.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) - _swift_js_push_i32(Int32(1)) - case .status(let param0, let param1, let param2): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - let __bjs_isSome_param1 = param1 != nil - if let __bjs_unwrapped_param1 = param1 { - __bjs_unwrapped_param1.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) - let __bjs_isSome_param2 = param2 != nil - if let __bjs_unwrapped_param2 = param2 { - __bjs_unwrapped_param2.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param2 ? 1 : 0) - _swift_js_push_i32(Int32(2)) - } - } } extension Precision: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { @@ -444,7 +257,7 @@ extension CardinalDirection: _BridgedSwiftCaseEnum { } extension TypedPayloadResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> TypedPayloadResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> TypedPayloadResult { switch caseId { case 0: return .precision(Precision.bridgeJSLiftParameter(_swift_js_pop_f32())) @@ -461,9 +274,7 @@ extension TypedPayloadResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .precision(let param0): param0.bridgeJSLowerStackReturn() @@ -489,47 +300,10 @@ extension TypedPayloadResult: _BridgedSwiftAssociatedValueEnum { return Int32(4) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> TypedPayloadResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> TypedPayloadResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .precision(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(0)) - case .direction(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - case .optPrecision(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_i32(Int32(2)) - case .optDirection(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_i32(Int32(3)) - case .empty: - _swift_js_push_i32(Int32(4)) - } - } } extension AllTypesResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> AllTypesResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> AllTypesResult { switch caseId { case 0: return .structPayload(Point.bridgeJSLiftParameter()) @@ -548,9 +322,7 @@ extension AllTypesResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .structPayload(let param0): param0.bridgeJSLowerReturn() @@ -571,42 +343,10 @@ extension AllTypesResult: _BridgedSwiftAssociatedValueEnum { return Int32(5) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> AllTypesResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> AllTypesResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .structPayload(let param0): - param0.bridgeJSLowerReturn() - _swift_js_push_i32(Int32(0)) - case .classPayload(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - case .jsObjectPayload(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(2)) - case .nestedEnum(let param0): - param0.bridgeJSLowerReturn() - _swift_js_push_i32(Int32(3)) - case .arrayPayload(let param0): - param0.bridgeJSLowerReturn() - _swift_js_push_i32(Int32(4)) - case .empty: - _swift_js_push_i32(Int32(5)) - } - } } extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> OptionalAllTypesResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> OptionalAllTypesResult { switch caseId { case 0: return .optStruct(Optional.bridgeJSLiftParameter()) @@ -625,9 +365,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .optStruct(let param0): param0.bridgeJSLowerReturn() @@ -660,50 +398,6 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { return Int32(5) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> OptionalAllTypesResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> OptionalAllTypesResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .optStruct(let param0): - param0.bridgeJSLowerReturn() - _swift_js_push_i32(Int32(0)) - case .optClass(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_i32(Int32(1)) - case .optJSObject(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_i32(Int32(2)) - case .optNestedEnum(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - _swift_js_push_i32(__bjs_unwrapped_param0.bridgeJSLowerParameter()) - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_i32(Int32(3)) - case .optArray(let param0): - param0.bridgeJSLowerReturn() - _swift_js_push_i32(Int32(4)) - case .empty: - _swift_js_push_i32(Int32(5)) - } - } } extension Point: _BridgedSwiftStruct { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift index 9b68b96ed..fcca0aaa3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift @@ -363,7 +363,7 @@ extension ExampleEnum: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { } extension Result: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> Result { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> Result { switch caseId { case 0: return .success(String.bridgeJSLiftParameter()) @@ -374,9 +374,7 @@ extension Result: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() @@ -386,27 +384,6 @@ extension Result: _BridgedSwiftAssociatedValueEnum { return Int32(1) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> Result { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> Result { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .success(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(0)) - case .failure(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - } - } } extension Priority: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.Global.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.Global.swift index a7b0578a9..6622ef3da 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.Global.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.Global.swift @@ -45,7 +45,7 @@ public func _bjs_Calculator_static_square(_ value: Int32) -> Int32 { } extension APIResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> APIResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> APIResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter()) @@ -56,9 +56,7 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() @@ -68,27 +66,6 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { return Int32(1) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> APIResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> APIResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .success(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(0)) - case .failure(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - } - } } @_expose(wasm, "bjs_APIResult_static_roundtrip") diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.swift index a7b0578a9..6622ef3da 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.swift @@ -45,7 +45,7 @@ public func _bjs_Calculator_static_square(_ value: Int32) -> Int32 { } extension APIResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> APIResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> APIResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter()) @@ -56,9 +56,7 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() @@ -68,27 +66,6 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { return Int32(1) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> APIResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> APIResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .success(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(0)) - case .failure(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - } - } } @_expose(wasm, "bjs_APIResult_static_roundtrip") diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift index d8b3c9bb8..57a963637 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift @@ -1188,7 +1188,7 @@ extension HttpStatus: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { } extension APIResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> APIResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> APIResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter()) @@ -1207,9 +1207,7 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() @@ -1230,38 +1228,6 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { return Int32(5) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> APIResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> APIResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .success(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(0)) - case .failure(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - case .flag(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(2)) - case .rate(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(3)) - case .precise(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(4)) - case .info: - _swift_js_push_i32(Int32(5)) - } - } } @_expose(wasm, "bjs_roundtripString") diff --git a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift index feca05b3b..90493f773 100644 --- a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift +++ b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift @@ -601,23 +601,42 @@ extension _BridgedSwiftCaseEnum { /// /// The conformance is automatically synthesized by the BridgeJS code generator. public protocol _BridgedSwiftAssociatedValueEnum: _BridgedSwiftTypeLoweredIntoVoidType, _BridgedSwiftStackType { - // MARK: ImportTS - @_spi(BridgeJS) consuming func bridgeJSLowerParameter() -> Int32 - @_spi(BridgeJS) static func bridgeJSLiftReturn(_ caseId: Int32) -> Self + /// Pops the payload of the associated value enum from the stack. + /// + /// - Parameter caseId: The enum case ID. + /// - Returns: The associated value enum with its payload popped from the stack. + @_spi(BridgeJS) static func bridgeJSStackPopPayload(_ caseId: Int32) -> Self - // MARK: ExportSwift - @_spi(BridgeJS) static func bridgeJSLiftParameter(_ caseId: Int32) -> Self - @_spi(BridgeJS) consuming func bridgeJSLowerReturn() -> Void + /// Pushes the payload of the associated value enum onto the stack. + /// + /// - Returns: The enum case ID. + @_spi(BridgeJS) consuming func bridgeJSStackPushPayload() -> Int32 } extension _BridgedSwiftAssociatedValueEnum { @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Self { - bridgeJSLiftParameter(_swift_js_pop_i32()) + bridgeJSStackPopPayload(_swift_js_pop_i32()) } @_spi(BridgeJS) public consuming func bridgeJSLowerStackReturn() { bridgeJSLowerReturn() } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ caseId: Int32) -> Self { + return bridgeJSStackPopPayload(caseId) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() { + _swift_js_push_i32(bridgeJSStackPushPayload()) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSStackPushPayload() + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ caseId: Int32) -> Self { + return bridgeJSStackPopPayload(caseId) + } } /// A protocol that Swift struct types conform to. diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index 745c56472..400829a5d 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -2026,7 +2026,7 @@ extension Internal.SupportedMethod: _BridgedSwiftCaseEnum { } extension APIResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> APIResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> APIResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter()) @@ -2045,9 +2045,7 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() @@ -2068,42 +2066,10 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { return Int32(5) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> APIResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> APIResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .success(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(0)) - case .failure(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - case .flag(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(2)) - case .rate(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(3)) - case .precise(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(4)) - case .info: - _swift_js_push_i32(Int32(5)) - } - } } extension ComplexResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> ComplexResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> ComplexResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter()) @@ -2124,9 +2090,7 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() @@ -2165,60 +2129,10 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { return Int32(6) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> ComplexResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> ComplexResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .success(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(0)) - case .error(let param0, let param1): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - case .location(let param0, let param1, let param2): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - param2.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(2)) - case .status(let param0, let param1, let param2): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - param2.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(3)) - case .coordinates(let param0, let param1, let param2): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - param2.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(4)) - case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - param2.bridgeJSLowerStackReturn() - param3.bridgeJSLowerStackReturn() - param4.bridgeJSLowerStackReturn() - param5.bridgeJSLowerStackReturn() - param6.bridgeJSLowerStackReturn() - param7.bridgeJSLowerStackReturn() - param8.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(5)) - case .info: - _swift_js_push_i32(Int32(6)) - } - } } extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> Utilities.Result { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> Utilities.Result { switch caseId { case 0: return .success(String.bridgeJSLiftParameter()) @@ -2231,9 +2145,7 @@ extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() @@ -2249,37 +2161,10 @@ extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { return Int32(2) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> Utilities.Result { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> Utilities.Result { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .success(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(0)) - case .failure(let param0, let param1): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - case .status(let param0, let param1, let param2): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - param2.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(2)) - } - } } extension API.NetworkingResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> API.NetworkingResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> API.NetworkingResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter()) @@ -2290,9 +2175,7 @@ extension API.NetworkingResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .success(let param0): param0.bridgeJSLowerStackReturn() @@ -2303,32 +2186,10 @@ extension API.NetworkingResult: _BridgedSwiftAssociatedValueEnum { return Int32(1) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> API.NetworkingResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> API.NetworkingResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .success(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(0)) - case .failure(let param0, let param1): - param0.bridgeJSLowerStackReturn() - param1.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - } - } } extension AllTypesResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> AllTypesResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> AllTypesResult { switch caseId { case 0: return .structPayload(Address.bridgeJSLiftParameter()) @@ -2349,9 +2210,7 @@ extension AllTypesResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .structPayload(let param0): param0.bridgeJSLowerReturn() @@ -2375,45 +2234,10 @@ extension AllTypesResult: _BridgedSwiftAssociatedValueEnum { return Int32(6) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> AllTypesResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> AllTypesResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .structPayload(let param0): - param0.bridgeJSLowerReturn() - _swift_js_push_i32(Int32(0)) - case .classPayload(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - case .jsObjectPayload(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(2)) - case .nestedEnum(let param0): - param0.bridgeJSLowerReturn() - _swift_js_push_i32(Int32(3)) - case .arrayPayload(let param0): - param0.bridgeJSLowerReturn() - _swift_js_push_i32(Int32(4)) - case .jsClassPayload(let param0): - param0.jsObject.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(5)) - case .empty: - _swift_js_push_i32(Int32(6)) - } - } } extension TypedPayloadResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> TypedPayloadResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> TypedPayloadResult { switch caseId { case 0: return .precision(Precision.bridgeJSLiftParameter(_swift_js_pop_f32())) @@ -2430,9 +2254,7 @@ extension TypedPayloadResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .precision(let param0): param0.bridgeJSLowerStackReturn() @@ -2458,43 +2280,6 @@ extension TypedPayloadResult: _BridgedSwiftAssociatedValueEnum { return Int32(4) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> TypedPayloadResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> TypedPayloadResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .precision(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(0)) - case .direction(let param0): - param0.bridgeJSLowerStackReturn() - _swift_js_push_i32(Int32(1)) - case .optPrecision(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_i32(Int32(2)) - case .optDirection(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_i32(Int32(3)) - case .empty: - _swift_js_push_i32(Int32(4)) - } - } } extension StaticCalculator: _BridgedSwiftCaseEnum { @@ -2803,7 +2588,7 @@ public func _bjs_StaticPropertyNamespace_NestedProperties_static_nestedDouble_se } extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> OptionalAllTypesResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> OptionalAllTypesResult { switch caseId { case 0: return .optStruct(Optional
.bridgeJSLiftParameter()) @@ -2824,9 +2609,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .optStruct(let param0): param0.bridgeJSLowerReturn() @@ -2866,61 +2649,10 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { return Int32(6) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> OptionalAllTypesResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> OptionalAllTypesResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .optStruct(let param0): - param0.bridgeJSLowerReturn() - _swift_js_push_i32(Int32(0)) - case .optClass(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_i32(Int32(1)) - case .optJSObject(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_i32(Int32(2)) - case .optNestedEnum(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - _swift_js_push_i32(__bjs_unwrapped_param0.bridgeJSLowerParameter()) - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_i32(Int32(3)) - case .optArray(let param0): - param0.bridgeJSLowerReturn() - _swift_js_push_i32(Int32(4)) - case .optJsClass(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.jsObject.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_i32(Int32(5)) - case .empty: - _swift_js_push_i32(Int32(6)) - } - } } extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { - private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> APIOptionalResult { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> APIOptionalResult { switch caseId { case 0: return .success(Optional.bridgeJSLiftParameter()) @@ -2933,9 +2665,7 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { } } - // MARK: Protocol Export - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { switch self { case .success(let param0): let __bjs_isSome_param0 = param0 != nil @@ -2975,57 +2705,6 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { return Int32(2) } } - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> APIOptionalResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> APIOptionalResult { - return _bridgeJSLiftFromCaseId(caseId) - } - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - switch self { - case .success(let param0): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - _swift_js_push_i32(Int32(0)) - case .failure(let param0, let param1): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - let __bjs_isSome_param1 = param1 != nil - if let __bjs_unwrapped_param1 = param1 { - __bjs_unwrapped_param1.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) - _swift_js_push_i32(Int32(1)) - case .status(let param0, let param1, let param2): - let __bjs_isSome_param0 = param0 != nil - if let __bjs_unwrapped_param0 = param0 { - __bjs_unwrapped_param0.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) - let __bjs_isSome_param1 = param1 != nil - if let __bjs_unwrapped_param1 = param1 { - __bjs_unwrapped_param1.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) - let __bjs_isSome_param2 = param2 != nil - if let __bjs_unwrapped_param2 = param2 { - __bjs_unwrapped_param2.bridgeJSLowerStackReturn() - } - _swift_js_push_i32(__bjs_isSome_param2 ? 1 : 0) - _swift_js_push_i32(Int32(2)) - } - } } extension Point: _BridgedSwiftStruct { From 8970445ff4a54536d1fc45f047899dc4886e30dc Mon Sep 17 00:00:00 2001 From: Krzysztof Rodak Date: Thu, 12 Feb 2026 10:19:49 +0100 Subject: [PATCH 32/40] NFC: BridgeJS: Simplify ExportSwift codegen by using no-arg bridgeJSLiftParameter() intrinsics --- .../Sources/BridgeJSCore/ExportSwift.swift | 55 ++++--------------- .../EnumAssociatedValue.swift | 6 +- .../BridgeJSCodegenTests/SwiftStruct.swift | 2 +- .../Generated/BridgeJS.swift | 18 +++--- 4 files changed, 24 insertions(+), 57 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index 5fb6f103f..600a24e2c 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -779,30 +779,11 @@ struct StackCodegen { func liftExpression(for type: BridgeType) -> ExprSyntax { switch type { case .string, .int, .uint, .bool, .float, .double, - .jsObject(nil), .jsValue, .swiftStruct, .swiftHeapObject: + .jsObject(nil), .jsValue, .swiftStruct, .swiftHeapObject, .unsafePointer, + .swiftProtocol, .caseEnum, .associatedValueEnum, .rawValueEnum: return "\(raw: type.swiftType).bridgeJSLiftParameter()" case .jsObject(let className?): return "\(raw: className)(unsafelyWrapping: JSObject.bridgeJSLiftParameter())" - case .unsafePointer: - return "\(raw: type.swiftType).bridgeJSLiftParameter()" - case .swiftProtocol(let protocolName): - return "Any\(raw: protocolName).bridgeJSLiftParameter(_swift_js_pop_i32())" - case .caseEnum: - return "\(raw: type.swiftType).bridgeJSLiftParameter(_swift_js_pop_i32())" - case .rawValueEnum(_, let rawType): - switch rawType { - case .string: - return - "\(raw: type.swiftType).bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())" - case .float: - return "\(raw: type.swiftType).bridgeJSLiftParameter(_swift_js_pop_f32())" - case .double: - return "\(raw: type.swiftType).bridgeJSLiftParameter(_swift_js_pop_f64())" - case .bool, .int, .int32, .int64, .uint, .uint32, .uint64: - return "\(raw: type.swiftType).bridgeJSLiftParameter(_swift_js_pop_i32())" - } - case .associatedValueEnum: - return "\(raw: type.swiftType).bridgeJSLiftParameter(_swift_js_pop_i32())" case .nullable(let wrappedType, let kind): return liftNullableExpression(wrappedType: wrappedType, kind: kind) case .array(let elementType): @@ -820,8 +801,6 @@ struct StackCodegen { switch elementType { case .jsObject(let className?) where className != "JSObject": return liftArrayExpressionInline(elementType: elementType) - case .swiftProtocol(let protocolName): - return "[Any\(raw: protocolName)].bridgeJSLiftParameter()" case .nullable, .closure: return liftArrayExpressionInline(elementType: elementType) case .void, .namespaceEnum: @@ -857,13 +836,6 @@ struct StackCodegen { return __dict.mapValues { \(raw: className)(unsafelyWrapping: $0) } }() """ - case .swiftProtocol(let protocolName): - return """ - { - let __dict = [String: JSObject].bridgeJSLiftParameter() - return __dict.mapValues { $0 as! Any\(raw: protocolName) } - }() - """ case .nullable, .closure: return liftDictionaryExpressionInline(valueType: valueType) case .void, .namespaceEnum: @@ -917,19 +889,14 @@ struct StackCodegen { varPrefix: String ) -> [CodeBlockItemSyntax] { switch type { - case .string, .int, .uint, .bool, .float, .double, .jsValue: - return ["\(raw: accessor).bridgeJSLowerStackReturn()"] - case .jsObject(nil): + case .string, .int, .uint, .bool, .float, .double, .jsValue, + .jsObject(nil), .swiftHeapObject, .unsafePointer, .closure, + .caseEnum, .rawValueEnum: return ["\(raw: accessor).bridgeJSLowerStackReturn()"] case .jsObject(_?): return ["\(raw: accessor).jsObject.bridgeJSLowerStackReturn()"] - case .swiftHeapObject, .unsafePointer, .closure: - return ["\(raw: accessor).bridgeJSLowerStackReturn()"] - case .swiftProtocol(let protocolName): - let wrapperName = "Any\(protocolName)" - return ["(\(raw: accessor) as! \(raw: wrapperName)).bridgeJSLowerStackReturn()"] - case .caseEnum, .rawValueEnum: - return ["\(raw: accessor).bridgeJSLowerStackReturn()"] + case .swiftProtocol: + return ["(\(raw: accessor) as! \(raw: type.swiftType)).bridgeJSLowerStackReturn()"] case .associatedValueEnum, .swiftStruct: return ["\(raw: accessor).bridgeJSLowerReturn()"] case .nullable(let wrappedType, _): @@ -951,8 +918,8 @@ struct StackCodegen { switch elementType { case .jsObject(let className?) where className != "JSObject": return ["\(raw: accessor).map { $0.jsObject }.bridgeJSLowerReturn()"] - case .swiftProtocol(let protocolName): - return ["\(raw: accessor).map { $0 as! Any\(raw: protocolName) }.bridgeJSLowerReturn()"] + case .swiftProtocol: + return ["\(raw: accessor).map { $0 as! \(raw: elementType.swiftType) }.bridgeJSLowerReturn()"] case .nullable, .closure: return lowerArrayStatementsInline( elementType: elementType, @@ -998,8 +965,8 @@ struct StackCodegen { switch valueType { case .jsObject(let className?) where className != "JSObject": return ["\(raw: accessor).mapValues { $0.jsObject }.bridgeJSLowerReturn()"] - case .swiftProtocol(let protocolName): - return ["\(raw: accessor).mapValues { $0 as! Any\(raw: protocolName) }.bridgeJSLowerReturn()"] + case .swiftProtocol: + return ["\(raw: accessor).mapValues { $0 as! \(raw: valueType.swiftType) }.bridgeJSLowerReturn()"] case .nullable, .closure: return lowerDictionaryStatementsInline( valueType: valueType, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift index 8705c929e..39582c9a9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift @@ -260,9 +260,9 @@ extension TypedPayloadResult: _BridgedSwiftAssociatedValueEnum { @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> TypedPayloadResult { switch caseId { case 0: - return .precision(Precision.bridgeJSLiftParameter(_swift_js_pop_f32())) + return .precision(Precision.bridgeJSLiftParameter()) case 1: - return .direction(CardinalDirection.bridgeJSLiftParameter(_swift_js_pop_i32())) + return .direction(CardinalDirection.bridgeJSLiftParameter()) case 2: return .optPrecision(Optional.bridgeJSLiftParameter()) case 3: @@ -312,7 +312,7 @@ extension AllTypesResult: _BridgedSwiftAssociatedValueEnum { case 2: return .jsObjectPayload(JSObject.bridgeJSLiftParameter()) case 3: - return .nestedEnum(APIResult.bridgeJSLiftParameter(_swift_js_pop_i32())) + return .nestedEnum(APIResult.bridgeJSLiftParameter()) case 4: return .arrayPayload([Int].bridgeJSLiftParameter()) case 5: diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.swift index 1ff0a4ce8..2e551452d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.swift @@ -223,7 +223,7 @@ fileprivate func _bjs_struct_lift_Session() -> Int32 { extension Measurement: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> Measurement { let optionalPrecision = Optional.bridgeJSLiftParameter() - let precision = Precision.bridgeJSLiftParameter(_swift_js_pop_f32()) + let precision = Precision.bridgeJSLiftParameter() let value = Double.bridgeJSLiftParameter() return Measurement(value: value, precision: precision, optionalPrecision: optionalPrecision) } diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index 400829a5d..07092d4bd 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -2198,7 +2198,7 @@ extension AllTypesResult: _BridgedSwiftAssociatedValueEnum { case 2: return .jsObjectPayload(JSObject.bridgeJSLiftParameter()) case 3: - return .nestedEnum(APIResult.bridgeJSLiftParameter(_swift_js_pop_i32())) + return .nestedEnum(APIResult.bridgeJSLiftParameter()) case 4: return .arrayPayload([Int].bridgeJSLiftParameter()) case 5: @@ -2240,9 +2240,9 @@ extension TypedPayloadResult: _BridgedSwiftAssociatedValueEnum { @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> TypedPayloadResult { switch caseId { case 0: - return .precision(Precision.bridgeJSLiftParameter(_swift_js_pop_f32())) + return .precision(Precision.bridgeJSLiftParameter()) case 1: - return .direction(Direction.bridgeJSLiftParameter(_swift_js_pop_i32())) + return .direction(Direction.bridgeJSLiftParameter()) case 2: return .optPrecision(Optional.bridgeJSLiftParameter()) case 3: @@ -2992,7 +2992,7 @@ fileprivate func _bjs_struct_lift_Contact() -> Int32 { extension Config: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> Config { - let status = Status.bridgeJSLiftParameter(_swift_js_pop_i32()) + let status = Status.bridgeJSLiftParameter() let direction = Optional.bridgeJSLiftParameter() let theme = Optional.bridgeJSLiftParameter() let name = String.bridgeJSLiftParameter() @@ -3100,7 +3100,7 @@ extension ValidationReport: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> ValidationReport { let outcome = Optional.bridgeJSLiftParameter() let status = Optional.bridgeJSLiftParameter() - let result = APIResult.bridgeJSLiftParameter(_swift_js_pop_i32()) + let result = APIResult.bridgeJSLiftParameter() let id = Int.bridgeJSLiftParameter() return ValidationReport(id: id, result: result, status: status, outcome: outcome) } @@ -3160,8 +3160,8 @@ extension AdvancedConfig: _BridgedSwiftStruct { let location = Optional.bridgeJSLiftParameter() let metadata = Optional.bridgeJSLiftParameter() let result = Optional.bridgeJSLiftParameter() - let status = Status.bridgeJSLiftParameter(_swift_js_pop_i32()) - let theme = Theme.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let status = Status.bridgeJSLiftParameter() + let theme = Theme.bridgeJSLiftParameter() let enabled = Bool.bridgeJSLiftParameter() let title = String.bridgeJSLiftParameter() let id = Int.bridgeJSLiftParameter() @@ -3226,8 +3226,8 @@ extension MeasurementConfig: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> MeasurementConfig { let optionalRatio = Optional.bridgeJSLiftParameter() let optionalPrecision = Optional.bridgeJSLiftParameter() - let ratio = Ratio.bridgeJSLiftParameter(_swift_js_pop_f64()) - let precision = Precision.bridgeJSLiftParameter(_swift_js_pop_f32()) + let ratio = Ratio.bridgeJSLiftParameter() + let precision = Precision.bridgeJSLiftParameter() return MeasurementConfig(precision: precision, ratio: ratio, optionalPrecision: optionalPrecision, optionalRatio: optionalRatio) } From d5ac7fa0c04cb55d125d077d7eb490d129c4ca02 Mon Sep 17 00:00:00 2001 From: Krzysztof Rodak Date: Thu, 12 Feb 2026 11:43:16 +0100 Subject: [PATCH 33/40] NFC: BridgeJS: Simplify ExportSwift codegen by removing redundant branches and extracting helpers --- .../Sources/BridgeJSCore/ExportSwift.swift | 104 +++++------------- .../EnumAssociatedValue.swift | 2 +- .../BridgeJSCodegenTests/Protocol.swift | 2 +- .../Generated/BridgeJS.swift | 8 +- 4 files changed, 36 insertions(+), 80 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index 600a24e2c..e324c866f 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -147,23 +147,9 @@ public class ExportSwift { } else { optionalSwiftType = "JSUndefinedOr" } - if case .swiftProtocol(let protocolName) = wrappedType { - let wrapperName = "Any\(protocolName)" - typeNameForIntrinsic = "\(optionalSwiftType)<\(wrapperName)>" - liftingExpr = ExprSyntax( - "\(raw: typeNameForIntrinsic).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" - ) - } else { - typeNameForIntrinsic = "\(optionalSwiftType)<\(wrappedType.swiftType)>" - liftingExpr = ExprSyntax( - "\(raw: typeNameForIntrinsic).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" - ) - } - case .swiftProtocol(let protocolName): - let wrapperName = "Any\(protocolName)" - typeNameForIntrinsic = wrapperName + typeNameForIntrinsic = "\(optionalSwiftType)<\(wrappedType.swiftType)>" liftingExpr = ExprSyntax( - "\(raw: wrapperName).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" + "\(raw: typeNameForIntrinsic).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" ) default: typeNameForIntrinsic = param.type.swiftType @@ -178,6 +164,20 @@ public class ExportSwift { } } + private func protocolCastSuffix(for returnType: BridgeType) -> (prefix: String, suffix: String) { + switch returnType { + case .swiftProtocol: + return ("", " as! \(returnType.swiftType)") + case .nullable(let wrappedType, _): + if case .swiftProtocol = wrappedType { + return ("(", ").flatMap { $0 as? \(wrappedType.swiftType) }") + } + return ("", "") + default: + return ("", "") + } + } + private func removeFirstLiftedParameter() -> (parameter: Parameter, expr: ExprSyntax) { let parameter = parameters.removeFirst() let expr = liftedParameterExprs.removeFirst() @@ -211,26 +211,10 @@ public class ExportSwift { if returnType == .void { return CodeBlockItemSyntax(item: .init(ExpressionStmtSyntax(expression: callExpr))) } else { - switch returnType { - case .swiftProtocol(let protocolName): - let wrapperName = "Any\(protocolName)" - return CodeBlockItemSyntax( - item: .init(DeclSyntax("let ret = \(raw: callExpr) as! \(raw: wrapperName)")) - ) - case .nullable(let wrappedType, _): - if case .swiftProtocol(let protocolName) = wrappedType { - let wrapperName = "Any\(protocolName)" - return CodeBlockItemSyntax( - item: .init( - DeclSyntax("let ret = (\(raw: callExpr)).flatMap { $0 as? \(raw: wrapperName) }") - ) - ) - } else { - return CodeBlockItemSyntax(item: .init(DeclSyntax("let ret = \(raw: callExpr)"))) - } - default: - return CodeBlockItemSyntax(item: .init(DeclSyntax("let ret = \(raw: callExpr)"))) - } + let (prefix, suffix) = protocolCastSuffix(for: returnType) + return CodeBlockItemSyntax( + item: .init(DeclSyntax("let ret = \(raw: prefix)\(raw: callExpr)\(raw: suffix)")) + ) } } @@ -244,20 +228,8 @@ public class ExportSwift { if returnType == .void { append("\(raw: name)") } else { - switch returnType { - case .swiftProtocol(let protocolName): - let wrapperName = "Any\(protocolName)" - append("let ret = \(raw: name) as! \(raw: wrapperName)") - case .nullable(let wrappedType, _): - if case .swiftProtocol(let protocolName) = wrappedType { - let wrapperName = "Any\(protocolName)" - append("let ret = \(raw: name).flatMap { $0 as? \(raw: wrapperName) }") - } else { - append("let ret = \(raw: name)") - } - default: - append("let ret = \(raw: name)") - } + let (prefix, suffix) = protocolCastSuffix(for: returnType) + append("let ret = \(raw: prefix)\(raw: name)\(raw: suffix)") } } @@ -301,20 +273,8 @@ public class ExportSwift { if returnType == .void { append("\(raw: selfExpr).\(raw: propertyName)") } else { - switch returnType { - case .swiftProtocol(let protocolName): - let wrapperName = "Any\(protocolName)" - append("let ret = \(raw: selfExpr).\(raw: propertyName) as! \(raw: wrapperName)") - case .nullable(let wrappedType, _): - if case .swiftProtocol(let protocolName) = wrappedType { - let wrapperName = "Any\(protocolName)" - append("let ret = \(raw: selfExpr).\(raw: propertyName).flatMap { $0 as? \(raw: wrapperName) }") - } else { - append("let ret = \(raw: selfExpr).\(raw: propertyName)") - } - default: - append("let ret = \(raw: selfExpr).\(raw: propertyName)") - } + let (prefix, suffix) = protocolCastSuffix(for: returnType) + append("let ret = \(raw: prefix)\(raw: selfExpr).\(raw: propertyName)\(raw: suffix)") } } @@ -1051,18 +1011,14 @@ struct StackCodegen { varPrefix: String ) -> [CodeBlockItemSyntax] { switch wrappedType { - case .string, .int, .uint, .bool, .float, .double, .jsValue: - return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"] - case .caseEnum, .rawValueEnum: - return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"] - case .swiftHeapObject: - return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"] - case .associatedValueEnum: - return ["_swift_js_push_i32(\(raw: unwrappedVar).bridgeJSLowerParameter())"] - case .jsObject(nil): - return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"] case .jsObject(_?): return ["\(raw: unwrappedVar).jsObject.bridgeJSLowerStackReturn()"] + case .swiftProtocol: + return ["(\(raw: unwrappedVar) as! \(raw: wrappedType.swiftType)).bridgeJSLowerStackReturn()"] + case .string, .int, .uint, .bool, .float, .double, .jsValue, + .jsObject(nil), .swiftHeapObject, .unsafePointer, .closure, + .caseEnum, .rawValueEnum, .associatedValueEnum: + return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"] default: return ["preconditionFailure(\"BridgeJS: unsupported optional wrapped type\")"] } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift index 39582c9a9..fa19b481c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift @@ -387,7 +387,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { case .optNestedEnum(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - _swift_js_push_i32(__bjs_unwrapped_param0.bridgeJSLowerParameter()) + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(3) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift index fcca0aaa3..4051f5c9e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift @@ -565,7 +565,7 @@ public func _bjs_MyViewController_delegate_set(_ _self: UnsafeMutableRawPointer, @_cdecl("bjs_MyViewController_secondDelegate_get") public func _bjs_MyViewController_secondDelegate_get(_ _self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let ret = MyViewController.bridgeJSLiftParameter(_self).secondDelegate.flatMap { $0 as? AnyMyViewControllerDelegate } + let ret = (MyViewController.bridgeJSLiftParameter(_self).secondDelegate).flatMap { $0 as? AnyMyViewControllerDelegate } return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index 07092d4bd..e01c41511 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -2631,7 +2631,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { case .optNestedEnum(let param0): let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - _swift_js_push_i32(__bjs_unwrapped_param0.bridgeJSLowerParameter()) + __bjs_unwrapped_param0.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) return Int32(3) @@ -3115,7 +3115,7 @@ extension ValidationReport: _BridgedSwiftStruct { _swift_js_push_i32(__bjs_isSome_status ? 1 : 0) let __bjs_isSome_outcome = self.outcome != nil if let __bjs_unwrapped_outcome = self.outcome { - _swift_js_push_i32(__bjs_unwrapped_outcome.bridgeJSLowerParameter()) + __bjs_unwrapped_outcome.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_outcome ? 1 : 0) } @@ -3176,7 +3176,7 @@ extension AdvancedConfig: _BridgedSwiftStruct { self.status.bridgeJSLowerStackReturn() let __bjs_isSome_result = self.result != nil if let __bjs_unwrapped_result = self.result { - _swift_js_push_i32(__bjs_unwrapped_result.bridgeJSLowerParameter()) + __bjs_unwrapped_result.bridgeJSLowerStackReturn() } _swift_js_push_i32(__bjs_isSome_result ? 1 : 0) let __bjs_isSome_metadata = self.metadata != nil @@ -7670,7 +7670,7 @@ public func _bjs_DataProcessorManager_processor_set(_ _self: UnsafeMutableRawPoi @_cdecl("bjs_DataProcessorManager_backupProcessor_get") public func _bjs_DataProcessorManager_backupProcessor_get(_ _self: UnsafeMutableRawPointer) -> Void { #if arch(wasm32) - let ret = DataProcessorManager.bridgeJSLiftParameter(_self).backupProcessor.flatMap { $0 as? AnyDataProcessor } + let ret = (DataProcessorManager.bridgeJSLiftParameter(_self).backupProcessor).flatMap { $0 as? AnyDataProcessor } return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") From 38a73c86edd302cc5dcebcdc389ec14b5b8a526f Mon Sep 17 00:00:00 2001 From: Krzysztof Rodak Date: Thu, 12 Feb 2026 13:21:34 +0100 Subject: [PATCH 34/40] NFC: BridgeJS: Further simplify codegen and JSValue intrinsics --- .../Sources/BridgeJSCore/ClosureCodegen.swift | 37 ++-- .../Sources/BridgeJSCore/ExportSwift.swift | 158 +++++++++--------- .../ImportedTypeInExportedInterface.swift | 11 +- .../JavaScriptKit/BridgeJSIntrinsics.swift | 42 ++--- .../Generated/BridgeJS.swift | 11 +- 5 files changed, 106 insertions(+), 153 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift index eefc63a7e..cbec4ba31 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift @@ -11,17 +11,17 @@ import BridgeJSUtilities public struct ClosureCodegen { public init() {} + private func swiftClosureType(for signature: ClosureSignature) -> String { + let closureParams = signature.parameters.map { "\($0.swiftType)" }.joined(separator: ", ") + let swiftEffects = (signature.isAsync ? " async" : "") + (signature.isThrows ? " throws" : "") + let swiftReturnType = signature.returnType.swiftType + return "(\(closureParams))\(swiftEffects) -> \(swiftReturnType)" + } + func renderClosureHelpers(_ signature: ClosureSignature) throws -> [DeclSyntax] { let mangledName = signature.mangleName let helperName = "_BJS_Closure_\(mangledName)" - - let closureParams = signature.parameters.enumerated().map { _, type in - "\(type.swiftType)" - }.joined(separator: ", ") - - let swiftEffects = (signature.isAsync ? " async" : "") + (signature.isThrows ? " throws" : "") - let swiftReturnType = signature.returnType.swiftType - let swiftClosureType = "(\(closureParams))\(swiftEffects) -> \(swiftReturnType)" + let swiftClosureType = swiftClosureType(for: signature) let externName = "invoke_js_callback_\(signature.moduleName)_\(mangledName)" @@ -72,7 +72,7 @@ public struct ClosureCodegen { } else { parameters = " (" - + signature.parameters.enumerated().map { index, param in + + signature.parameters.enumerated().map { index, _ in "param\(index)" }.joined(separator: ", ") + ")" } @@ -113,12 +113,7 @@ public struct ClosureCodegen { } func renderClosureInvokeHandler(_ signature: ClosureSignature) throws -> DeclSyntax { - let closureParams = signature.parameters.enumerated().map { _, type in - "\(type.swiftType)" - }.joined(separator: ", ") - let swiftEffects = (signature.isAsync ? " async" : "") + (signature.isThrows ? " throws" : "") - let swiftReturnType = signature.returnType.swiftType - let swiftClosureType = "(\(closureParams))\(swiftEffects) -> \(swiftReturnType)" + let swiftClosureType = swiftClosureType(for: signature) let boxType = "_BridgeJSTypedClosureBox<\(swiftClosureType)>" let abiName = "invoke_swift_closure_\(signature.moduleName)_\(signature.mangleName)" @@ -144,17 +139,7 @@ public struct ClosureCodegen { let closureCallExpr = ExprSyntax("closure(\(raw: liftedParams.joined(separator: ", ")))") - // Determine return type - let abiReturnWasmType: WasmCoreType? - if signature.returnType == .void { - abiReturnWasmType = nil - } else if let wasmType = try signature.returnType.loweringReturnInfo().returnType { - abiReturnWasmType = wasmType - } else { - abiReturnWasmType = nil - } - - let throwReturn = abiReturnWasmType?.swiftReturnPlaceholderStmt ?? "return" + let abiReturnWasmType = try signature.returnType.loweringReturnInfo().returnType // Build signature using SwiftSignatureBuilder let funcSignature = SwiftSignatureBuilder.buildABIFunctionSignature( diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index e324c866f..bb42e9d1e 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -482,12 +482,7 @@ public class ExportSwift { } if function.effects.isStatic, let staticContext = function.staticContext { - let callName: String - switch staticContext { - case .className(let baseName), .enumName(let baseName), .structName(let baseName), - .namespaceEnum(let baseName): - callName = "\(baseName).\(function.name)" - } + let callName = "\(staticContextBaseName(staticContext)).\(function.name)" builder.call(name: callName, returnType: function.returnType) } else { builder.call(name: function.name, returnType: function.returnType) @@ -497,17 +492,61 @@ public class ExportSwift { return builder.render(abiName: function.abiName) } + private func staticContextBaseName(_ staticContext: StaticContext) -> String { + switch staticContext { + case .className(let baseName), .enumName(let baseName), .structName(let baseName), + .namespaceEnum(let baseName): + return baseName + } + } + + private func renderSingleExportedConstructor( + constructor: ExportedConstructor, + callName: String, + returnType: BridgeType + ) throws -> DeclSyntax { + let builder = ExportedThunkBuilder(effects: constructor.effects) + for param in constructor.parameters { + try builder.liftParameter(param: param) + } + builder.call(name: callName, returnType: returnType) + try builder.lowerReturnValue(returnType: returnType) + return builder.render(abiName: constructor.abiName) + } + + private func renderSingleExportedMethod( + method: ExportedFunction, + ownerTypeName: String, + instanceSelfType: BridgeType + ) throws -> DeclSyntax { + let builder = ExportedThunkBuilder(effects: method.effects) + if !method.effects.isStatic { + try builder.liftParameter(param: Parameter(label: nil, name: "_self", type: instanceSelfType)) + } + for param in method.parameters { + try builder.liftParameter(param: param) + } + + if method.effects.isStatic { + builder.call(name: "\(ownerTypeName).\(method.name)", returnType: method.returnType) + } else { + builder.callMethod(methodName: method.name, returnType: method.returnType) + } + try builder.lowerReturnValue(returnType: method.returnType) + return builder.render(abiName: method.abiName) + } + func renderSingleExportedStruct(struct structDef: ExportedStruct) throws -> [DeclSyntax] { var decls: [DeclSyntax] = [] if let constructor = structDef.constructor { - let builder = ExportedThunkBuilder(effects: constructor.effects) - for param in constructor.parameters { - try builder.liftParameter(param: param) - } - builder.call(name: structDef.swiftCallName, returnType: .swiftStruct(structDef.swiftCallName)) - try builder.lowerReturnValue(returnType: .swiftStruct(structDef.swiftCallName)) - decls.append(builder.render(abiName: constructor.abiName)) + decls.append( + try renderSingleExportedConstructor( + constructor: constructor, + callName: structDef.swiftCallName, + returnType: .swiftStruct(structDef.swiftCallName) + ) + ) } for property in structDef.properties where property.isStatic { @@ -520,28 +559,13 @@ public class ExportSwift { } for method in structDef.methods { - let builder = ExportedThunkBuilder(effects: method.effects) - - if method.effects.isStatic { - for param in method.parameters { - try builder.liftParameter(param: param) - } - builder.call(name: "\(structDef.swiftCallName).\(method.name)", returnType: method.returnType) - } else { - try builder.liftParameter( - param: Parameter(label: nil, name: "_self", type: .swiftStruct(structDef.swiftCallName)) - ) - for param in method.parameters { - try builder.liftParameter(param: param) - } - builder.callMethod( - methodName: method.name, - returnType: method.returnType + decls.append( + try renderSingleExportedMethod( + method: method, + ownerTypeName: structDef.swiftCallName, + instanceSelfType: .swiftStruct(structDef.swiftCallName) ) - } - - try builder.lowerReturnValue(returnType: method.returnType) - decls.append(builder.render(abiName: method.abiName)) + ) } return decls @@ -598,55 +622,29 @@ public class ExportSwift { var decls: [DeclSyntax] = [] if let constructor = klass.constructor { - let builder = ExportedThunkBuilder(effects: constructor.effects) - for param in constructor.parameters { - try builder.liftParameter(param: param) - } - builder.call(name: klass.swiftCallName, returnType: BridgeType.swiftHeapObject(klass.name)) - try builder.lowerReturnValue(returnType: BridgeType.swiftHeapObject(klass.name)) - decls.append(builder.render(abiName: constructor.abiName)) + decls.append( + try renderSingleExportedConstructor( + constructor: constructor, + callName: klass.swiftCallName, + returnType: .swiftHeapObject(klass.name) + ) + ) } for method in klass.methods { - let builder = ExportedThunkBuilder(effects: method.effects) - - if method.effects.isStatic { - for param in method.parameters { - try builder.liftParameter(param: param) - } - builder.call(name: "\(klass.swiftCallName).\(method.name)", returnType: method.returnType) - } else { - try builder.liftParameter( - param: Parameter(label: nil, name: "_self", type: BridgeType.swiftHeapObject(klass.swiftCallName)) - ) - for param in method.parameters { - try builder.liftParameter(param: param) - } - builder.callMethod( - methodName: method.name, - returnType: method.returnType + decls.append( + try renderSingleExportedMethod( + method: method, + ownerTypeName: klass.swiftCallName, + instanceSelfType: .swiftHeapObject(klass.swiftCallName) ) - } - try builder.lowerReturnValue(returnType: method.returnType) - decls.append(builder.render(abiName: method.abiName)) + ) } // Generate property getters and setters for property in klass.properties { - if property.isStatic { - decls.append( - contentsOf: try renderSingleExportedProperty( - property: property, - context: .classStatic(klass: klass) - ) - ) - } else { - decls.append( - contentsOf: try renderSingleExportedProperty( - property: property, - context: .classInstance(klass: klass) - ) - ) - } + let context: PropertyRenderingContext = + property.isStatic ? .classStatic(klass: klass) : .classInstance(klass: klass) + decls.append(contentsOf: try renderSingleExportedProperty(property: property, context: context)) } do { @@ -760,7 +758,7 @@ struct StackCodegen { func liftArrayExpression(elementType: BridgeType) -> ExprSyntax { switch elementType { case .jsObject(let className?) where className != "JSObject": - return liftArrayExpressionInline(elementType: elementType) + return "[JSObject].bridgeJSLiftParameter().map { \(raw: className)(unsafelyWrapping: $0) }" case .nullable, .closure: return liftArrayExpressionInline(elementType: elementType) case .void, .namespaceEnum: @@ -992,8 +990,7 @@ struct StackCodegen { let innerStatements = lowerUnwrappedOptionalStatements( wrappedType: wrappedType, - unwrappedVar: "__bjs_unwrapped_\(varPrefix)", - varPrefix: varPrefix + unwrappedVar: "__bjs_unwrapped_\(varPrefix)" ) for stmt in innerStatements { statements.append(stmt.description) @@ -1007,8 +1004,7 @@ struct StackCodegen { private func lowerUnwrappedOptionalStatements( wrappedType: BridgeType, - unwrappedVar: String, - varPrefix: String + unwrappedVar: String ) -> [CodeBlockItemSyntax] { switch wrappedType { case .jsObject(_?): diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift index cd0f56694..5708e7de9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift @@ -76,16 +76,7 @@ public func _bjs_makeFoo() -> Int32 { @_cdecl("bjs_processFooArray") public func _bjs_processFooArray() -> Void { #if arch(wasm32) - let ret = processFooArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [Foo] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append(Foo(unsafelyWrapping: JSObject.bridgeJSLiftParameter())) - } - __result.reverse() - return __result - }()) + let ret = processFooArray(_: [JSObject].bridgeJSLiftParameter().map { Foo(unsafelyWrapping: $0) }) ret.map { $0.jsObject }.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") diff --git a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift index 90493f773..ff219531d 100644 --- a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift +++ b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift @@ -386,6 +386,19 @@ extension JSObject: _BridgedSwiftStackType { extension JSValue: _BridgedSwiftStackType { public typealias StackLiftResult = JSValue + @_transparent + private static func bridgeJSRetainPayloadIfNeeded(kind: Int32, payload1: Int32) -> Int32 { + guard let kindEnum = JavaScriptValueKind(rawValue: UInt32(kind)) else { + return payload1 + } + switch kindEnum { + case .string, .object, .symbol, .bigInt: + return _swift_js_retain(payload1) + default: + return payload1 + } + } + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (kind: Int32, payload1: Int32, payload2: Double) { return withRawJSValue { raw in ( @@ -409,17 +422,7 @@ extension JSValue: _BridgedSwiftStackType { _ payload1: Int32, _ payload2: Double ) -> JSValue { - let retainedPayload1: Int32 - if let kindEnum = JavaScriptValueKind(rawValue: UInt32(kind)) { - switch kindEnum { - case .string, .object, .symbol, .bigInt: - retainedPayload1 = _swift_js_retain(payload1) - default: - retainedPayload1 = payload1 - } - } else { - retainedPayload1 = payload1 - } + let retainedPayload1 = bridgeJSRetainPayloadIfNeeded(kind: kind, payload1: payload1) guard let kindEnum = JavaScriptValueKind(rawValue: UInt32(kind)) else { fatalError("Invalid JSValue kind: \(kind)") @@ -440,25 +443,12 @@ extension JSValue: _BridgedSwiftStackType { } @_spi(BridgeJS) public static func bridgeJSLiftReturn() -> JSValue { - let payload2 = _swift_js_pop_f64() - let payload1 = _swift_js_pop_i32() - let kind = _swift_js_pop_i32() - return bridgeJSLiftParameter(kind, payload1, payload2) + bridgeJSLiftParameter() } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { let lowered = bridgeJSLowerParameter() - let retainedPayload1: Int32 - if let kind = JavaScriptValueKind(rawValue: UInt32(lowered.kind)) { - switch kind { - case .string, .object, .symbol, .bigInt: - retainedPayload1 = _swift_js_retain(lowered.payload1) - default: - retainedPayload1 = lowered.payload1 - } - } else { - retainedPayload1 = lowered.payload1 - } + let retainedPayload1 = Self.bridgeJSRetainPayloadIfNeeded(kind: lowered.kind, payload1: lowered.payload1) _swift_js_push_i32(lowered.kind) _swift_js_push_i32(retainedPayload1) _swift_js_push_f64(lowered.payload2) diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index e01c41511..a606ad741 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -5555,16 +5555,7 @@ public func _bjs_roundTripOptionalJSObjectArray() -> Void { @_cdecl("bjs_roundTripFooArray") public func _bjs_roundTripFooArray() -> Void { #if arch(wasm32) - let ret = roundTripFooArray(_: { - let __count = Int(_swift_js_pop_i32()) - var __result: [Foo] = [] - __result.reserveCapacity(__count) - for _ in 0..<__count { - __result.append(Foo(unsafelyWrapping: JSObject.bridgeJSLiftParameter())) - } - __result.reverse() - return __result - }()) + let ret = roundTripFooArray(_: [JSObject].bridgeJSLiftParameter().map { Foo(unsafelyWrapping: $0) }) ret.map { $0.jsObject }.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") From e68262d70c9c8448d8dd21a50ca3157bb082f237 Mon Sep 17 00:00:00 2001 From: Krzysztof Rodak Date: Thu, 12 Feb 2026 16:31:12 +0100 Subject: [PATCH 35/40] BridgeJS: Consolidate optional and pointer runtime intrinsics --- .../JavaScriptKit/BridgeJSIntrinsics.swift | 641 ++++++------------ 1 file changed, 199 insertions(+), 442 deletions(-) diff --git a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift index 90493f773..713088adf 100644 --- a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift +++ b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift @@ -520,7 +520,13 @@ extension _JSBridgedClass { @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ id: Int32) -> Self { Self(unsafelyWrapping: JSObject.bridgeJSLiftParameter(id)) } + @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Self { + bridgeJSLiftParameter(_swift_js_pop_i32()) + } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Int32 { jsObject.bridgeJSLowerReturn() } + @_spi(BridgeJS) public consuming func bridgeJSLowerStackReturn() { + _swift_js_push_i32(bridgeJSLowerReturn()) + } } /// A protocol that Swift protocol wrappers exposed from JavaScript must conform to. @@ -996,160 +1002,86 @@ private func _swift_js_pop_pointer_extern() -> UnsafeMutableRawPointer { // MARK: - UnsafePointer family -extension UnsafeMutableRawPointer: _BridgedSwiftStackType { - // MARK: ImportTS - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> UnsafeMutableRawPointer { self } - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn( - _ pointer: UnsafeMutableRawPointer - ) - -> UnsafeMutableRawPointer - { - pointer - } - - // MARK: ExportSwift - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter( - _ pointer: UnsafeMutableRawPointer - ) - -> UnsafeMutableRawPointer - { - pointer - } - @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> UnsafeMutableRawPointer { - bridgeJSLiftParameter(_swift_js_pop_pointer()) - } - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> UnsafeMutableRawPointer { self } - @_spi(BridgeJS) public consuming func bridgeJSLowerStackReturn() { - _swift_js_push_pointer(self) - } +public protocol _BridgedSwiftUnsafePointerLike: _BridgedSwiftStackType { + @_spi(BridgeJS) func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer + @_spi(BridgeJS) static func bridgeJSFromUnsafeMutableRawPointer(_ pointer: UnsafeMutableRawPointer) -> Self } -extension UnsafeRawPointer: _BridgedSwiftStackType { +extension _BridgedSwiftUnsafePointerLike { // MARK: ImportTS @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> UnsafeMutableRawPointer { - UnsafeMutableRawPointer(mutating: self) + bridgeJSToUnsafeMutableRawPointer() } - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn( - _ pointer: UnsafeMutableRawPointer - ) - -> UnsafeRawPointer - { - UnsafeRawPointer(pointer) + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ pointer: UnsafeMutableRawPointer) -> Self { + bridgeJSFromUnsafeMutableRawPointer(pointer) } // MARK: ExportSwift - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter( - _ pointer: UnsafeMutableRawPointer - ) - -> UnsafeRawPointer - { - UnsafeRawPointer(pointer) + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ pointer: UnsafeMutableRawPointer) -> Self { + bridgeJSFromUnsafeMutableRawPointer(pointer) } - @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> UnsafeRawPointer { + @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Self { bridgeJSLiftParameter(_swift_js_pop_pointer()) } @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> UnsafeMutableRawPointer { - bridgeJSLowerParameter() + bridgeJSToUnsafeMutableRawPointer() } @_spi(BridgeJS) public consuming func bridgeJSLowerStackReturn() { - _swift_js_push_pointer(UnsafeMutableRawPointer(mutating: self)) + _swift_js_push_pointer(bridgeJSToUnsafeMutableRawPointer()) } } -extension OpaquePointer: _BridgedSwiftStackType { - // MARK: ImportTS - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> UnsafeMutableRawPointer { - UnsafeMutableRawPointer(mutating: UnsafeRawPointer(self)) - } - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn( +extension UnsafeMutableRawPointer: _BridgedSwiftUnsafePointerLike { + @_spi(BridgeJS) @_transparent public func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer { self } + @_spi(BridgeJS) @_transparent public static func bridgeJSFromUnsafeMutableRawPointer( _ pointer: UnsafeMutableRawPointer - ) - -> OpaquePointer - { - OpaquePointer(UnsafeRawPointer(pointer)) + ) -> UnsafeMutableRawPointer { + pointer } +} - // MARK: ExportSwift - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter( - _ pointer: UnsafeMutableRawPointer - ) - -> OpaquePointer - { - OpaquePointer(UnsafeRawPointer(pointer)) - } - @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> OpaquePointer { - bridgeJSLiftParameter(_swift_js_pop_pointer()) - } - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> UnsafeMutableRawPointer { - bridgeJSLowerParameter() +extension UnsafeRawPointer: _BridgedSwiftUnsafePointerLike { + @_spi(BridgeJS) @_transparent public func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer { + UnsafeMutableRawPointer(mutating: self) } - @_spi(BridgeJS) public consuming func bridgeJSLowerStackReturn() { - _swift_js_push_pointer(UnsafeMutableRawPointer(mutating: UnsafeRawPointer(self))) + @_spi(BridgeJS) @_transparent public static func bridgeJSFromUnsafeMutableRawPointer( + _ pointer: UnsafeMutableRawPointer + ) -> UnsafeRawPointer { + UnsafeRawPointer(pointer) } } -extension UnsafePointer: _BridgedSwiftStackType { - // MARK: ImportTS - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> UnsafeMutableRawPointer { +extension OpaquePointer: _BridgedSwiftUnsafePointerLike { + @_spi(BridgeJS) @_transparent public func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer { UnsafeMutableRawPointer(mutating: UnsafeRawPointer(self)) } - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn( + @_spi(BridgeJS) @_transparent public static func bridgeJSFromUnsafeMutableRawPointer( _ pointer: UnsafeMutableRawPointer - ) - -> UnsafePointer - { - UnsafeRawPointer(pointer).assumingMemoryBound(to: Pointee.self) + ) -> OpaquePointer { + OpaquePointer(UnsafeRawPointer(pointer)) } +} - // MARK: ExportSwift - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter( +extension UnsafePointer: _BridgedSwiftUnsafePointerLike { + @_spi(BridgeJS) @_transparent public func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer { + UnsafeMutableRawPointer(mutating: UnsafeRawPointer(self)) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSFromUnsafeMutableRawPointer( _ pointer: UnsafeMutableRawPointer - ) - -> UnsafePointer - { + ) -> UnsafePointer { UnsafeRawPointer(pointer).assumingMemoryBound(to: Pointee.self) } - @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> UnsafePointer { - bridgeJSLiftParameter(_swift_js_pop_pointer()) - } - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> UnsafeMutableRawPointer { - bridgeJSLowerParameter() - } - @_spi(BridgeJS) public consuming func bridgeJSLowerStackReturn() { - _swift_js_push_pointer(bridgeJSLowerParameter()) - } } -extension UnsafeMutablePointer: _BridgedSwiftStackType { - // MARK: ImportTS - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> UnsafeMutableRawPointer { +extension UnsafeMutablePointer: _BridgedSwiftUnsafePointerLike { + @_spi(BridgeJS) @_transparent public func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer { UnsafeMutableRawPointer(self) } - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn( - _ pointer: UnsafeMutableRawPointer - ) - -> UnsafeMutablePointer - { - pointer.assumingMemoryBound(to: Pointee.self) - } - - // MARK: ExportSwift - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter( + @_spi(BridgeJS) @_transparent public static func bridgeJSFromUnsafeMutableRawPointer( _ pointer: UnsafeMutableRawPointer - ) - -> UnsafeMutablePointer - { + ) -> UnsafeMutablePointer { pointer.assumingMemoryBound(to: Pointee.self) } - @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> UnsafeMutablePointer { - bridgeJSLiftParameter(_swift_js_pop_pointer()) - } - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> UnsafeMutableRawPointer { - bridgeJSLowerParameter() - } - @_spi(BridgeJS) public consuming func bridgeJSLowerStackReturn() { - _swift_js_push_pointer(bridgeJSLowerParameter()) - } } // Optional support for JSTypedClosure @@ -1167,145 +1099,178 @@ extension Optional { } } -extension Optional where Wrapped == Bool { - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> ( - isSome: Int32, value: Int32 - ) { - switch consume self { +extension Optional { + @usableFromInline @_transparent func _bridgeJSLowerParameter( + noneValue: Payload, + lowerWrapped: (Wrapped) -> Payload + ) -> (isSome: Int32, value: Payload) { + switch self { case .none: - return (isSome: 0, value: 0) + return (isSome: 0, value: noneValue) case .some(let wrapped): - return (isSome: 1, value: wrapped.bridgeJSLowerParameter()) + return (isSome: 1, value: lowerWrapped(wrapped)) } } - @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Bool? { + @usableFromInline @_transparent static func _bridgeJSLiftParameter( + _ isSome: Int32, + _ payload: Payload, + liftWrapped: (Payload) -> Wrapped + ) -> Wrapped? { if isSome == 0 { return nil - } else { - return Bool.bridgeJSLiftParameter(wrappedValue) - } - } - - @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Bool? { - let isSome = _swift_js_pop_i32() - let wrappedValue = _swift_js_pop_i32() - return bridgeJSLiftParameter(isSome, wrappedValue) - } - - @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ value: Int32) -> Bool? { - switch value { - case -1: - return nil - case 0: - return false - case 1: - return true - default: - return nil // Treat invalid values as null } + return liftWrapped(payload) } - @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - switch consume self { + @usableFromInline @_transparent func _bridgeJSLowerReturn( + noneValue: Payload, + lowerWrapped: (Wrapped) -> Payload, + write: (Int32, Payload) -> Void + ) { + switch self { case .none: - _swift_js_return_optional_bool(0, 0) - case .some(let value): - _swift_js_return_optional_bool(1, value.bridgeJSLowerReturn()) + write(0, noneValue) + case .some(let wrapped): + write(1, lowerWrapped(wrapped)) } } } -extension Optional where Wrapped == Int { - // MARK: ExportSwift +public protocol _BridgedSwiftOptionalScalarBridge: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType { + @_spi(BridgeJS) static func bridgeJSPopOptionalScalarPayload() -> WasmCoreType + @_spi(BridgeJS) static var bridgeJSOptionalScalarNonePayload: WasmCoreType { get } + @_spi(BridgeJS) static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: WasmCoreType) +} - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> ( - isSome: Int32, value: Int32 - ) { - switch consume self { - case .none: - return (isSome: 0, value: 0) - case .some(let wrapped): - return (isSome: 1, value: wrapped.bridgeJSLowerParameter()) - } +public protocol _BridgedSwiftOptionalScalarSideChannelBridge: _BridgedSwiftOptionalScalarBridge { + @_spi(BridgeJS) static func bridgeJSReadOptionalSideChannelPresence() -> Int32 + @_spi(BridgeJS) static func bridgeJSReadOptionalSideChannelPayload() -> WasmCoreType +} + +extension Bool: _BridgedSwiftOptionalScalarBridge { + @_spi(BridgeJS) public static func bridgeJSPopOptionalScalarPayload() -> Int32 { _swift_js_pop_i32() } + @_spi(BridgeJS) public static var bridgeJSOptionalScalarNonePayload: Int32 { 0 } + @_spi(BridgeJS) public static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: Int32) { + _swift_js_return_optional_bool(isSome, value) } +} - @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Int? { - if isSome == 0 { - return nil - } else { - return Int.bridgeJSLiftParameter(wrappedValue) - } +extension Int: _BridgedSwiftOptionalScalarSideChannelBridge { + @_spi(BridgeJS) public static func bridgeJSPopOptionalScalarPayload() -> Int32 { _swift_js_pop_i32() } + @_spi(BridgeJS) public static var bridgeJSOptionalScalarNonePayload: Int32 { 0 } + @_spi(BridgeJS) public static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: Int32) { + _swift_js_return_optional_int(isSome, value) + } + @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPresence() -> Int32 { + _swift_js_get_optional_int_presence() + } + @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPayload() -> Int32 { + _swift_js_get_optional_int_value() } +} - @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Int? { - let isSome = _swift_js_pop_i32() - let wrappedValue = _swift_js_pop_i32() - return bridgeJSLiftParameter(isSome, wrappedValue) +extension UInt: _BridgedSwiftOptionalScalarSideChannelBridge { + @_spi(BridgeJS) public static func bridgeJSPopOptionalScalarPayload() -> Int32 { _swift_js_pop_i32() } + @_spi(BridgeJS) public static var bridgeJSOptionalScalarNonePayload: Int32 { 0 } + @_spi(BridgeJS) public static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: Int32) { + _swift_js_return_optional_int(isSome, value) } + @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPresence() -> Int32 { + _swift_js_get_optional_int_presence() + } + @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPayload() -> Int32 { + _swift_js_get_optional_int_value() + } +} - @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Int? { - let isSome = _swift_js_get_optional_int_presence() - if isSome == 0 { - return nil - } else { - return Int.bridgeJSLiftReturn(_swift_js_get_optional_int_value()) - } +extension Float: _BridgedSwiftOptionalScalarSideChannelBridge { + @_spi(BridgeJS) public static func bridgeJSPopOptionalScalarPayload() -> Float32 { _swift_js_pop_f32() } + @_spi(BridgeJS) public static var bridgeJSOptionalScalarNonePayload: Float32 { 0.0 } + @_spi(BridgeJS) public static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: Float32) { + _swift_js_return_optional_float(isSome, value) + } + @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPresence() -> Int32 { + _swift_js_get_optional_float_presence() } + @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPayload() -> Float32 { + _swift_js_get_optional_float_value() + } +} - @_spi(BridgeJS) public func bridgeJSLowerReturn() -> Void { - switch self { - case .none: - _swift_js_return_optional_int(0, 0) - case .some(let value): - _swift_js_return_optional_int(1, value.bridgeJSLowerReturn()) - } +extension Double: _BridgedSwiftOptionalScalarSideChannelBridge { + @_spi(BridgeJS) public static func bridgeJSPopOptionalScalarPayload() -> Float64 { _swift_js_pop_f64() } + @_spi(BridgeJS) public static var bridgeJSOptionalScalarNonePayload: Float64 { 0.0 } + @_spi(BridgeJS) public static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: Float64) { + _swift_js_return_optional_double(isSome, value) + } + @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPresence() -> Int32 { + _swift_js_get_optional_double_presence() + } + @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPayload() -> Float64 { + _swift_js_get_optional_double_value() } } -extension Optional where Wrapped == UInt { +extension Optional where Wrapped: _BridgedSwiftOptionalScalarBridge { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> ( - isSome: Int32, value: Int32 + isSome: Int32, value: Wrapped.WasmCoreType ) { switch consume self { case .none: - return (isSome: 0, value: 0) + return (isSome: 0, value: Wrapped.bridgeJSOptionalScalarNonePayload) case .some(let wrapped): return (isSome: 1, value: wrapped.bridgeJSLowerParameter()) } } - @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> UInt? { + @_spi(BridgeJS) public static func bridgeJSLiftParameter( + _ isSome: Int32, + _ wrappedValue: Wrapped.WasmCoreType + ) -> Wrapped? { if isSome == 0 { return nil - } else { - return UInt.bridgeJSLiftParameter(wrappedValue) } + return Wrapped.bridgeJSLiftParameter(wrappedValue) } - @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> UInt? { + @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Wrapped? { let isSome = _swift_js_pop_i32() - let wrappedValue = _swift_js_pop_i32() + let wrappedValue = Wrapped.bridgeJSPopOptionalScalarPayload() return bridgeJSLiftParameter(isSome, wrappedValue) } - @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> UInt? { - let isSome = _swift_js_get_optional_int_presence() + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + switch consume self { + case .none: + Wrapped.bridgeJSWriteOptionalReturn(0, Wrapped.bridgeJSOptionalScalarNonePayload) + case .some(let value): + Wrapped.bridgeJSWriteOptionalReturn(1, value.bridgeJSLowerReturn()) + } + } +} + +extension Optional where Wrapped: _BridgedSwiftOptionalScalarSideChannelBridge { + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Wrapped? { + let isSome = Wrapped.bridgeJSReadOptionalSideChannelPresence() if isSome == 0 { return nil - } else { - return UInt.bridgeJSLiftReturn(_swift_js_get_optional_int_value()) } + return Wrapped.bridgeJSLiftReturn(Wrapped.bridgeJSReadOptionalSideChannelPayload()) } +} - @_spi(BridgeJS) public func bridgeJSLowerReturn() -> Void { - switch self { - case .none: - _swift_js_return_optional_int(0, 0) - case .some(let value): - _swift_js_return_optional_int(1, value.bridgeJSLowerReturn()) +extension Optional where Wrapped == Bool { + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ value: Int32) -> Bool? { + switch value { + case -1: + return nil + case 0: + return false + case 1: + return true + default: + return nil // Treat invalid values as null } } } @@ -1315,21 +1280,12 @@ extension Optional where Wrapped == String { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> ( isSome: Int32, value: Int32 ) { - switch consume self { - case .none: - return (isSome: 0, value: 0) - case .some(let wrapped): - return (isSome: 1, value: wrapped.bridgeJSLowerParameter()) - } + _bridgeJSLowerParameter(noneValue: 0, lowerWrapped: { $0.bridgeJSLowerParameter() }) } @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ bytes: Int32, _ count: Int32) -> String? { - if isSome == 0 { - return nil - } else { - return String.bridgeJSLiftParameter(bytes, count) - } + _bridgeJSLiftParameter(isSome, (bytes, count), liftWrapped: { String.bridgeJSLiftParameter($0.0, $0.1) }) } @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> String? { @@ -1365,20 +1321,11 @@ extension Optional where Wrapped == JSObject { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> ( isSome: Int32, value: Int32 ) { - switch consume self { - case .none: - return (isSome: 0, value: 0) - case .some(let wrapped): - return (isSome: 1, value: wrapped.bridgeJSLowerParameter()) - } + _bridgeJSLowerParameter(noneValue: 0, lowerWrapped: { $0.bridgeJSLowerParameter() }) } @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ objectId: Int32) -> JSObject? { - if isSome == 0 { - return nil - } else { - return JSObject.bridgeJSLiftParameter(objectId) - } + _bridgeJSLiftParameter(isSome, objectId, liftWrapped: JSObject.bridgeJSLiftParameter) } @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> JSObject? { @@ -1388,13 +1335,11 @@ extension Optional where Wrapped == JSObject { } @_spi(BridgeJS) public func bridgeJSLowerReturn() -> Void { - switch self { - case .none: - _swift_js_return_optional_object(0, 0) - case .some(let value): - let retainedId = value.bridgeJSLowerReturn() - _swift_js_return_optional_object(1, retainedId) - } + _bridgeJSLowerReturn( + noneValue: 0, + lowerWrapped: { $0.bridgeJSLowerReturn() }, + write: _swift_js_return_optional_object + ) } } @@ -1496,11 +1441,7 @@ extension Optional where Wrapped: _BridgedSwiftProtocolWrapper { // MARK: ExportSwift @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ objectId: Int32) -> Wrapped? { - if isSome == 0 { - return nil - } else { - return Wrapped.bridgeJSLiftParameter(objectId) - } + _bridgeJSLiftParameter(isSome, objectId, liftWrapped: Wrapped.bridgeJSLiftParameter) } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { @@ -1569,11 +1510,7 @@ extension Optional where Wrapped: _BridgedSwiftHeapObject { _ isSome: Int32, _ pointer: UnsafeMutableRawPointer ) -> Optional { - if isSome == 0 { - return nil - } else { - return Wrapped.bridgeJSLiftParameter(pointer) - } + _bridgeJSLiftParameter(isSome, pointer, liftWrapped: Wrapped.bridgeJSLiftParameter) } @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Wrapped? { @@ -1601,120 +1538,16 @@ extension Optional where Wrapped: _BridgedSwiftHeapObject { } } } -extension Optional where Wrapped == Float { - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> ( - isSome: Int32, value: Float32 - ) { - switch consume self { - case .none: - return (isSome: 0, value: 0.0) - case .some(let wrapped): - return (isSome: 1, value: wrapped.bridgeJSLowerParameter()) - } - } - - @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Float32) -> Float? { - if isSome == 0 { - return nil - } else { - return Float.bridgeJSLiftParameter(wrappedValue) - } - } - - @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Float? { - let isSome = _swift_js_pop_i32() - let wrappedValue = _swift_js_pop_f32() - return bridgeJSLiftParameter(isSome, wrappedValue) - } - - @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Float? { - let isSome = _swift_js_get_optional_float_presence() - if isSome == 0 { - return nil - } else { - return Float.bridgeJSLiftReturn(_swift_js_get_optional_float_value()) - } - } - - @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - switch consume self { - case .none: - _swift_js_return_optional_float(0, 0.0) - case .some(let value): - _swift_js_return_optional_float(1, value.bridgeJSLowerReturn()) - } - } -} - -/// Optional support for Double -extension Optional where Wrapped == Double { - // MARK: ExportSwift - - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> ( - isSome: Int32, value: Float64 - ) { - switch consume self { - case .none: - return (isSome: 0, value: 0.0) - case .some(let wrapped): - return (isSome: 1, value: wrapped.bridgeJSLowerParameter()) - } - } - - @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Float64) -> Double? { - if isSome == 0 { - return nil - } else { - return Double.bridgeJSLiftParameter(wrappedValue) - } - } - - @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Double? { - let isSome = _swift_js_pop_i32() - let wrappedValue = _swift_js_pop_f64() - return bridgeJSLiftParameter(isSome, wrappedValue) - } - - @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Double? { - let isSome = _swift_js_get_optional_double_presence() - if isSome == 0 { - return nil - } else { - return Double.bridgeJSLiftReturn(_swift_js_get_optional_double_value()) - } - } - - @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - switch consume self { - case .none: - _swift_js_return_optional_double(0, 0.0) - case .some(let value): - _swift_js_return_optional_double(1, value.bridgeJSLowerReturn()) - } - } -} - /// Optional support for case enums extension Optional where Wrapped: _BridgedSwiftCaseEnum { // MARK: ExportSwift @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { - switch consume self { - case .none: - return (isSome: 0, value: 0) - case .some(let value): - return (isSome: 1, value: value.bridgeJSLowerParameter()) - } + _bridgeJSLowerParameter(noneValue: 0, lowerWrapped: { $0.bridgeJSLowerParameter() }) } @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Wrapped? { - if isSome == 0 { - return nil - } else { - return Wrapped.bridgeJSLiftParameter(wrappedValue) - } + _bridgeJSLiftParameter(isSome, wrappedValue, liftWrapped: Wrapped.bridgeJSLiftParameter) } @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Wrapped? { @@ -1732,12 +1565,11 @@ extension Optional where Wrapped: _BridgedSwiftCaseEnum { } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - switch consume self { - case .none: - _swift_js_return_optional_int(0, 0) - case .some(let value): - _swift_js_return_optional_int(1, value.bridgeJSLowerReturn()) - } + _bridgeJSLowerReturn( + noneValue: 0, + lowerWrapped: { $0.bridgeJSLowerReturn() }, + write: _swift_js_return_optional_int + ) } } @@ -2030,12 +1862,17 @@ where Wrapped: _BridgedSwiftGenericOptionalStackType { // MARK: - _BridgedAsOptional (JSUndefinedOr) delegating to Optional -extension _BridgedAsOptional where Wrapped == Bool { - @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { +extension _BridgedAsOptional where Wrapped: _BridgedSwiftOptionalScalarBridge { + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> ( + isSome: Int32, value: Wrapped.WasmCoreType + ) { asOptional.bridgeJSLowerParameter() } - @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Self { + @_spi(BridgeJS) public static func bridgeJSLiftParameter( + _ isSome: Int32, + _ wrappedValue: Wrapped.WasmCoreType + ) -> Self { Self(optional: Optional.bridgeJSLiftParameter(isSome, wrappedValue)) } @@ -2043,56 +1880,20 @@ extension _BridgedAsOptional where Wrapped == Bool { Self(optional: Optional.bridgeJSLiftParameter()) } - @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ value: Int32) -> Self { - Self(optional: Optional.bridgeJSLiftReturn(value)) - } - @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { asOptional.bridgeJSLowerReturn() } } -extension _BridgedAsOptional where Wrapped == Int { - @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { - asOptional.bridgeJSLowerParameter() - } - - @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Self { - Self(optional: Optional.bridgeJSLiftParameter(isSome, wrappedValue)) - } - - @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Self { - Self(optional: Optional.bridgeJSLiftParameter()) - } - +extension _BridgedAsOptional where Wrapped: _BridgedSwiftOptionalScalarSideChannelBridge { @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self { Self(optional: Optional.bridgeJSLiftReturnFromSideChannel()) } - - @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - asOptional.bridgeJSLowerReturn() - } } -extension _BridgedAsOptional where Wrapped == UInt { - @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { - asOptional.bridgeJSLowerParameter() - } - - @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Self { - Self(optional: Optional.bridgeJSLiftParameter(isSome, wrappedValue)) - } - - @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Self { - Self(optional: Optional.bridgeJSLiftParameter()) - } - - @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self { - Self(optional: Optional.bridgeJSLiftReturnFromSideChannel()) - } - - @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - asOptional.bridgeJSLowerReturn() +extension _BridgedAsOptional where Wrapped == Bool { + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ value: Int32) -> Self { + Self(optional: Optional.bridgeJSLiftReturn(value)) } } @@ -2182,50 +1983,6 @@ extension _BridgedAsOptional where Wrapped: _BridgedSwiftHeapObject { } } -extension _BridgedAsOptional where Wrapped == Float { - @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Float32) { - asOptional.bridgeJSLowerParameter() - } - - @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Float32) -> Self { - Self(optional: Optional.bridgeJSLiftParameter(isSome, wrappedValue)) - } - - @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Self { - Self(optional: Optional.bridgeJSLiftParameter()) - } - - @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self { - Self(optional: Optional.bridgeJSLiftReturnFromSideChannel()) - } - - @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - asOptional.bridgeJSLowerReturn() - } -} - -extension _BridgedAsOptional where Wrapped == Double { - @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Float64) { - asOptional.bridgeJSLowerParameter() - } - - @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Float64) -> Self { - Self(optional: Optional.bridgeJSLiftParameter(isSome, wrappedValue)) - } - - @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Self { - Self(optional: Optional.bridgeJSLiftParameter()) - } - - @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self { - Self(optional: Optional.bridgeJSLiftReturnFromSideChannel()) - } - - @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - asOptional.bridgeJSLowerReturn() - } -} - extension _BridgedAsOptional where Wrapped: _BridgedSwiftCaseEnum { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { asOptional.bridgeJSLowerParameter() From ac72422ca67aacefa94b79590ffdfc1c1ac11921 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 13 Feb 2026 02:34:05 +0900 Subject: [PATCH 36/40] Merge pull request #627 from swiftwasm/katei/bf1a-fix-ts2swift-for Fix ts2swift alias struct naming and docs --- .../TS2Swift/JavaScript/src/processor.js | 6 +++--- .../test/__snapshots__/ts2swift.test.js.snap | 19 +++++++++++++++++++ .../test/fixtures/TypeAliasObject.d.ts | 11 +++++++++++ 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/TypeAliasObject.d.ts diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/processor.js b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/processor.js index 302058036..c71ff6fe5 100644 --- a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/processor.js +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/processor.js @@ -747,8 +747,8 @@ export class TypeProcessor { * @private */ visitStructuredType(type, diagnosticNode, members) { - const symbol = type.getSymbol() ?? type.aliasSymbol; - const name = symbol?.name ?? this.checker.typeToString(type); + const symbol = type.aliasSymbol ?? type.getSymbol(); + const name = type.aliasSymbol?.name ?? symbol?.name ?? this.checker.typeToString(type); if (!name) return; if (this.emittedStructuredTypeNames.has(name)) return; this.emittedStructuredTypeNames.add(name); @@ -760,7 +760,7 @@ export class TypeProcessor { if (jsNameArg) args.push(jsNameArg); const annotation = this.renderMacroAnnotation("JSClass", args); const typeName = this.renderIdentifier(swiftName); - const docNode = symbol?.getDeclarations()?.[0] ?? diagnosticNode; + const docNode = type.aliasSymbol?.getDeclarations()?.[0] ?? symbol?.getDeclarations()?.[0] ?? diagnosticNode; if (docNode) { this.emitDocComment(docNode, { indent: "" }); } diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/__snapshots__/ts2swift.test.js.snap b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/__snapshots__/ts2swift.test.js.snap index 343f8795b..49814a996 100644 --- a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/__snapshots__/ts2swift.test.js.snap +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/__snapshots__/ts2swift.test.js.snap @@ -426,6 +426,25 @@ exports[`ts2swift > snapshots Swift output for TypeAlias.d.ts > TypeAlias 1`] = " `; +exports[`ts2swift > snapshots Swift output for TypeAliasObject.d.ts > TypeAliasObject 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit + +@JSFunction func console() throws(JSException) -> Console + +/// Console from the environment. +@JSClass struct Console { + /// Log a message. + @JSFunction func log(_ message: String) throws(JSException) -> Void +} +" +`; + exports[`ts2swift > snapshots Swift output for TypeScriptClass.d.ts > TypeScriptClass 1`] = ` "// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/TypeAliasObject.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/TypeAliasObject.d.ts new file mode 100644 index 000000000..55ffdfa3a --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/TypeAliasObject.d.ts @@ -0,0 +1,11 @@ +/** + * Console from the environment. + */ +export type Console = { + /** + * Log a message. + */ + log(message: string): void; +}; + +export function console(): Console; From b3ddd88f6565ed9e5fa173350712e15e97cb7ac9 Mon Sep 17 00:00:00 2001 From: Krzysztof Rodak Date: Thu, 12 Feb 2026 18:40:34 +0100 Subject: [PATCH 37/40] Prevent cross-module inlining of f32/f64 @_extern(wasm) functions --- .../JavaScriptKit/BridgeJSIntrinsics.swift | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift index ff219531d..0715703a3 100644 --- a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift +++ b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift @@ -723,22 +723,30 @@ where Self: RawRepresentable, RawValue: _BridgedSwiftTypeLoweredIntoSingleWasmCo #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_push_f32") -@_spi(BridgeJS) public func _swift_js_push_f32(_ value: Float32) +private func _swift_js_push_f32_extern(_ value: Float32) #else -@_spi(BridgeJS) public func _swift_js_push_f32(_ value: Float32) { +private func _swift_js_push_f32_extern(_ value: Float32) { _onlyAvailableOnWasm() } #endif +@_spi(BridgeJS) @inline(never) public func _swift_js_push_f32(_ value: Float32) { + _swift_js_push_f32_extern(value) +} + #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_push_f64") -@_spi(BridgeJS) public func _swift_js_push_f64(_ value: Float64) +private func _swift_js_push_f64_extern(_ value: Float64) #else -@_spi(BridgeJS) public func _swift_js_push_f64(_ value: Float64) { +private func _swift_js_push_f64_extern(_ value: Float64) { _onlyAvailableOnWasm() } #endif +@_spi(BridgeJS) @inline(never) public func _swift_js_push_f64(_ value: Float64) { + _swift_js_push_f64_extern(value) +} + #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_pop_i32") @_spi(BridgeJS) public func _swift_js_pop_i32() -> Int32 @@ -750,22 +758,30 @@ where Self: RawRepresentable, RawValue: _BridgedSwiftTypeLoweredIntoSingleWasmCo #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_pop_f32") -@_spi(BridgeJS) public func _swift_js_pop_f32() -> Float32 +private func _swift_js_pop_f32_extern() -> Float32 #else -@_spi(BridgeJS) public func _swift_js_pop_f32() -> Float32 { +private func _swift_js_pop_f32_extern() -> Float32 { _onlyAvailableOnWasm() } #endif +@_spi(BridgeJS) @inline(never) public func _swift_js_pop_f32() -> Float32 { + _swift_js_pop_f32_extern() +} + #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_pop_f64") -@_spi(BridgeJS) public func _swift_js_pop_f64() -> Float64 +private func _swift_js_pop_f64_extern() -> Float64 #else -@_spi(BridgeJS) public func _swift_js_pop_f64() -> Float64 { +private func _swift_js_pop_f64_extern() -> Float64 { _onlyAvailableOnWasm() } #endif +@_spi(BridgeJS) @inline(never) public func _swift_js_pop_f64() -> Float64 { + _swift_js_pop_f64_extern() +} + // MARK: Struct bridging helpers (JS-side lowering/raising) #if arch(wasm32) From e34f3824edcb9d08f2f127162f3c4a33bf318ca5 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 13 Feb 2026 10:21:24 +0900 Subject: [PATCH 38/40] BridgeJS: add runtime coverage for `public @JS struct` (#629) BridgeJS: add runtime coverage for public JS structs --- .../Generated/BridgeJS.swift | 67 +++++++++++++++ .../Generated/JavaScript/BridgeJS.json | 83 +++++++++++++++++++ Tests/BridgeJSRuntimeTests/StructAPIs.swift | 14 ++++ Tests/prelude.mjs | 3 + 4 files changed, 167 insertions(+) diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index a606ad741..e24775f43 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -2884,6 +2884,62 @@ public func _bjs_DataPoint_init(_ x: Float64, _ y: Float64, _ labelBytes: Int32, #endif } +extension PublicPoint: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> PublicPoint { + let y = Int.bridgeJSLiftParameter() + let x = Int.bridgeJSLiftParameter() + return PublicPoint(x: x, y: y) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { + self.x.bridgeJSLowerStackReturn() + self.y.bridgeJSLowerStackReturn() + } + + public init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_PublicPoint(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + public func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_PublicPoint())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_PublicPoint") +fileprivate func _bjs_struct_lower_PublicPoint(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_PublicPoint(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_PublicPoint") +fileprivate func _bjs_struct_lift_PublicPoint() -> Int32 +#else +fileprivate func _bjs_struct_lift_PublicPoint() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_PublicPoint_init") +@_cdecl("bjs_PublicPoint_init") +public func _bjs_PublicPoint_init(_ x: Int32, _ y: Int32) -> Void { + #if arch(wasm32) + let ret = PublicPoint(x: Int.bridgeJSLiftParameter(x), y: Int.bridgeJSLiftParameter(y)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + extension Address: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> Address { let zipCode = Optional.bridgeJSLiftParameter() @@ -5954,6 +6010,17 @@ public func _bjs_roundTripDataPoint() -> Void { #endif } +@_expose(wasm, "bjs_roundTripPublicPoint") +@_cdecl("bjs_roundTripPublicPoint") +public func _bjs_roundTripPublicPoint() -> Void { + #if arch(wasm32) + let ret = roundTripPublicPoint(_: PublicPoint.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_roundTripContact") @_cdecl("bjs_roundTripContact") public func _bjs_roundTripContact() -> Void { diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json index 7e2d4d855..fc650b37d 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json @@ -11131,6 +11131,31 @@ } } }, + { + "abiName" : "bjs_roundTripPublicPoint", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripPublicPoint", + "parameters" : [ + { + "label" : "_", + "name" : "point", + "type" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } + }, { "abiName" : "bjs_roundTripContact", "effects" : { @@ -12196,6 +12221,64 @@ ], "swiftCallName" : "DataPoint" }, + { + "constructor" : { + "abiName" : "bjs_PublicPoint_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "x", + "name" : "x", + "type" : { + "int" : { + + } + } + }, + { + "label" : "y", + "name" : "y", + "type" : { + "int" : { + + } + } + } + ] + }, + "explicitAccessControl" : "public", + "methods" : [ + + ], + "name" : "PublicPoint", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "x", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "y", + "type" : { + "int" : { + + } + } + } + ], + "swiftCallName" : "PublicPoint" + }, { "methods" : [ diff --git a/Tests/BridgeJSRuntimeTests/StructAPIs.swift b/Tests/BridgeJSRuntimeTests/StructAPIs.swift index 49869e0f5..38e7b12e6 100644 --- a/Tests/BridgeJSRuntimeTests/StructAPIs.swift +++ b/Tests/BridgeJSRuntimeTests/StructAPIs.swift @@ -40,6 +40,16 @@ } } +@JS public struct PublicPoint { + public var x: Int + public var y: Int + + @JS public init(x: Int, y: Int) { + self.x = x + self.y = y + } +} + @JS struct Address { var street: String var city: String @@ -168,6 +178,10 @@ return data } +@JS public func roundTripPublicPoint(_ point: PublicPoint) -> PublicPoint { + point +} + @JS func roundTripContact(_ contact: Contact) -> Contact { return contact } diff --git a/Tests/prelude.mjs b/Tests/prelude.mjs index efb168a6d..ec37bdbc4 100644 --- a/Tests/prelude.mjs +++ b/Tests/prelude.mjs @@ -890,6 +890,9 @@ function testStructSupport(exports) { const data2 = { x: 0.0, y: 0.0, label: "", optCount: null, optFlag: null }; assert.deepEqual(exports.roundTripDataPoint(data2), data2); + const publicPoint = { x: 9, y: -3 }; + assert.deepEqual(exports.roundTripPublicPoint(publicPoint), publicPoint); + const pointerFields1 = { raw: 1, mutRaw: 4, opaque: 1024, ptr: 65536, mutPtr: 2 }; assert.deepEqual(exports.roundTripPointerFields(pointerFields1), pointerFields1); From 6682a2e7e70ba1744da1e0896b7f54a2c98e8c42 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 13 Feb 2026 13:47:04 +0900 Subject: [PATCH 39/40] BridgeJS: Prepare for MVP release for documentation and relaxing feature gates (#630) * BridgeJS: Make `@JSClass`, `@JSFunction`, etc generally available without @_spi(Experimental) * BridgeJS: Remove JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS feature gate * BridgeJS: Update documentation for MVP release * [skip ci] Update READMEs --- Benchmarks/README.md | 2 +- .../Sources/Generated/BridgeJS.Macros.swift | 2 +- Examples/ExportSwift/README.md | 2 +- .../Generated/BridgeJS.Macros.swift | 2 +- Examples/PlayBridgeJS/build.sh | 2 +- Makefile | 2 +- Plugins/BridgeJS/README.md | 10 +- .../Sources/TS2Swift/JavaScript/src/cli.js | 2 +- .../test/__snapshots__/ts2swift.test.js.snap | 42 +- Plugins/PackageToJS/Sources/PackageToJS.swift | 5 - README.md | 44 +- .../BridgeJS/Ahead-of-Time-Code-Generation.md | 17 +- .../BridgeJS/BridgeJS-Configuration.md | 2 +- .../BridgeJS-Internals/BridgeJS-Internals.md | 11 + .../BridgeJS-Internals/Design-Rationale.md | 38 ++ .../Bringing-Swift-Closures-to-JavaScript.md | 80 ++++ .../BridgeJS/Exporting-Swift-to-JavaScript.md | 59 +-- .../Exporting-Swift/Exporting-Swift-Array.md | 2 +- .../Exporting-Swift/Exporting-Swift-Class.md | 5 +- .../Exporting-Swift-Closure.md | 9 +- .../Exporting-Swift-Default-Parameters.md | 4 +- .../Exporting-Swift/Exporting-Swift-Enum.md | 2 +- .../Exporting-Swift-Function.md | 2 +- .../Exporting-Swift-Optional.md | 10 +- .../Exporting-Swift-Protocols.md | 20 +- .../Exporting-Swift-Static-Functions.md | 12 +- .../Exporting-Swift-Static-Properties.md | 10 +- .../Exporting-Swift/Exporting-Swift-Struct.md | 4 +- .../Exporting-Swift/Using-Namespace.md | 6 +- .../BridgeJS/Generating-from-TypeScript.md | 419 ++++++++++++++++++ .../Importing-JavaScript-into-Swift.md | 98 ++++ .../Importing-JS-Class.md | 54 +++ .../Importing-JS-Function.md | 51 +++ .../Importing-JS-Variable.md | 59 +++ .../Importing-TypeScript-into-Swift.md | 185 -------- .../Importing-TS-Class.md | 64 --- .../Importing-TS-Function.md | 60 --- .../Importing-TS-Interface.md | 34 -- .../Importing-TS-TypeAlias.md | 47 -- .../Articles/BridgeJS/Introducing-BridgeJS.md | 32 ++ .../Articles/BridgeJS/Setting-up-BridgeJS.md | 60 +++ .../Articles/BridgeJS/Supported-Types.md | 34 +- .../Documentation.docc/Articles/FAQ.md | 28 ++ .../Documentation.docc/Documentation.md | 13 +- Sources/JavaScriptKit/Macros.swift | 12 +- .../ClosureSupportTests.swift | 2 +- .../DictionaryTests.swift | 2 +- .../BridgeJSRuntimeTests/ExportAPITests.swift | 2 +- .../Generated/BridgeJS.Macros.swift | 2 +- .../ImportArrayAPIs.swift | 2 +- .../ImportStructAPIs.swift | 2 +- .../OptionalSupportTests.swift | 2 +- Tests/BridgeJSRuntimeTests/StructAPIs.swift | 2 +- .../SwiftClassSupportTests.swift | 2 +- 54 files changed, 1091 insertions(+), 585 deletions(-) create mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Internals/BridgeJS-Internals.md create mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Internals/Design-Rationale.md create mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Bringing-Swift-Closures-to-JavaScript.md create mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Generating-from-TypeScript.md create mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript-into-Swift.md create mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Class.md create mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Function.md create mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Variable.md delete mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript-into-Swift.md delete mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript/Importing-TS-Class.md delete mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript/Importing-TS-Function.md delete mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript/Importing-TS-Interface.md delete mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript/Importing-TS-TypeAlias.md create mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Introducing-BridgeJS.md create mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Setting-up-BridgeJS.md create mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/FAQ.md diff --git a/Benchmarks/README.md b/Benchmarks/README.md index f7264b6b7..65d867eba 100644 --- a/Benchmarks/README.md +++ b/Benchmarks/README.md @@ -7,7 +7,7 @@ This directory contains performance benchmarks for JavaScriptKit. Before running the benchmarks, you need to build the test suite: ```bash -JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --swift-sdk $SWIFT_SDK_ID js -c release +swift package --swift-sdk $SWIFT_SDK_ID js -c release ``` ## Running Benchmarks diff --git a/Benchmarks/Sources/Generated/BridgeJS.Macros.swift b/Benchmarks/Sources/Generated/BridgeJS.Macros.swift index 39a46d22c..40fc29e91 100644 --- a/Benchmarks/Sources/Generated/BridgeJS.Macros.swift +++ b/Benchmarks/Sources/Generated/BridgeJS.Macros.swift @@ -4,7 +4,7 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func benchmarkHelperNoop() throws(JSException) -> Void diff --git a/Examples/ExportSwift/README.md b/Examples/ExportSwift/README.md index 57d419295..39c66f0a6 100644 --- a/Examples/ExportSwift/README.md +++ b/Examples/ExportSwift/README.md @@ -5,7 +5,7 @@ This example demonstrates how to export Swift functions to JavaScript. 1. Build the project: ```sh - env JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --swift-sdk $SWIFT_SDK_ID js --use-cdn + swift package --swift-sdk $SWIFT_SDK_ID js --use-cdn ``` 2. Serve the files: diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.Macros.swift b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.Macros.swift index c619a8883..4a87a6d38 100644 --- a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.Macros.swift +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.Macros.swift @@ -4,7 +4,7 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func createTS2Swift() throws(JSException) -> TS2Swift diff --git a/Examples/PlayBridgeJS/build.sh b/Examples/PlayBridgeJS/build.sh index d2589f798..31c07896c 100755 --- a/Examples/PlayBridgeJS/build.sh +++ b/Examples/PlayBridgeJS/build.sh @@ -1,5 +1,5 @@ #!/bin/bash set -euxo pipefail -env JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1}}" \ +swift package --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1}}" \ plugin --allow-writing-to-package-directory \ js --use-cdn --output ./Bundle -c "${1:-debug}" diff --git a/Makefile b/Makefile index 135465a73..270eb9b36 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ unittest: echo "SWIFT_SDK_ID is not set. Run 'swift sdk list' and pass a matching SDK, e.g. 'make unittest SWIFT_SDK_ID='."; \ exit 2; \ } - env JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --swift-sdk "$(SWIFT_SDK_ID)" \ + swift package --swift-sdk "$(SWIFT_SDK_ID)" \ $(TRACING_ARGS) \ --disable-sandbox \ js test --prelude ./Tests/prelude.mjs -Xnode --expose-gc diff --git a/Plugins/BridgeJS/README.md b/Plugins/BridgeJS/README.md index 0559dc3fb..0b6ad121e 100644 --- a/Plugins/BridgeJS/README.md +++ b/Plugins/BridgeJS/README.md @@ -1,17 +1,17 @@ # BridgeJS > [!IMPORTANT] -> This feature is still experimental, and the API may change frequently. Use at your own risk with `JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1` environment variable. +> This feature is still experimental, and the API may change frequently. Use at your own risk. > [!NOTE] -> This documentation is intended for JavaScriptKit developers, not JavaScriptKit users. For user documentation, see [Exporting Swift to JavaScript](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/exporting-swift-to-javascript) and [Importing TypeScript into Swift](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/importing-typescript-into-swift). +> This documentation is intended for JavaScriptKit developers, not JavaScriptKit users. For user documentation, see [Introducing BridgeJS](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/introducing-bridgejs), [Setting up BridgeJS](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/setting-up-bridgejs), [Exporting Swift to JavaScript](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/exporting-swift-to-javascript), [Importing JavaScript into Swift](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/importing-javascript-into-swift), and [Generating bindings from TypeScript](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/generating-from-typescript). ## Overview BridgeJS provides easy interoperability between Swift and JavaScript/TypeScript. It enables: -1. **Importing TypeScript APIs into Swift**: Use TypeScript/JavaScript APIs directly from Swift code -2. **Exporting Swift APIs to JavaScript**: Make your Swift APIs available to JavaScript code +1. **Export Swift to JavaScript** – Expose Swift functions, classes, and types to JavaScript; the plugin generates TypeScript definitions (`.d.ts`) for the exported API. +2. **Import JavaScript into Swift** – Make JavaScript/TypeScript APIs callable from Swift with macro-annotated bindings or bindings generated from a TypeScript declaration file (`bridge-js.d.ts`). The workflow is: @@ -161,7 +161,7 @@ Return values use direct Wasm returns for primitives, and imported intrinsic fun - **Structs/Arrays/Enums**: Copy semantics - data serialized across boundary. No cleanup needed. - **Closures**: Boxed on source side, released when GC'd on either side. -For detailed semantics, see the [How It Works sections](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/exporting-swift-class#How-It-Works) in the user documentation. +For detailed semantics, see the [How It Works sections](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/exporting-swift-class#how-it-works) in the user documentation. ## Testing diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js index 766cd0432..98453ebf1 100644 --- a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js @@ -123,7 +123,7 @@ export function run(filePath, options) { "// To update this file, just rebuild your project or run", "// `swift package bridge-js`.", "", - "@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit", + "@_spi(BridgeJS) import JavaScriptKit", "", "", ].join("\n"); diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/__snapshots__/ts2swift.test.js.snap b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/__snapshots__/ts2swift.test.js.snap index 49814a996..85d1da0de 100644 --- a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/__snapshots__/ts2swift.test.js.snap +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/__snapshots__/ts2swift.test.js.snap @@ -7,7 +7,7 @@ exports[`ts2swift > snapshots Swift output for ArrayParameter.d.ts > ArrayParame // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func processNumbers(_ values: [Double]) throws(JSException) -> Void @@ -30,7 +30,7 @@ exports[`ts2swift > snapshots Swift output for Async.d.ts > Async 1`] = ` // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func asyncReturnVoid() throws(JSException) -> JSPromise @@ -55,7 +55,7 @@ exports[`ts2swift > snapshots Swift output for Documentation.d.ts > Documentatio // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit /// Return a greeting for a user. /// @@ -112,7 +112,7 @@ exports[`ts2swift > snapshots Swift output for Interface.d.ts > Interface 1`] = // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func returnAnimatable() throws(JSException) -> Animatable @@ -130,7 +130,7 @@ exports[`ts2swift > snapshots Swift output for InvalidPropertyNames.d.ts > Inval // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func createArrayBuffer() throws(JSException) -> ArrayBufferLike @@ -178,7 +178,7 @@ exports[`ts2swift > snapshots Swift output for MultipleImportedTypes.d.ts > Mult // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func createDatabaseConnection(_ config: JSValue) throws(JSException) -> DatabaseConnection @@ -215,7 +215,7 @@ exports[`ts2swift > snapshots Swift output for ObjectLikeTypes.d.ts > ObjectLike // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func acceptObject(_ v: JSObject) throws(JSException) -> Void " @@ -228,7 +228,7 @@ exports[`ts2swift > snapshots Swift output for OptionalNullUndefined.d.ts > Opti // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func roundTripNumberNull(_ value: Optional) throws(JSException) -> Optional @@ -269,7 +269,7 @@ exports[`ts2swift > snapshots Swift output for PrimitiveParameters.d.ts > Primit // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func check(_ a: Double, _ b: Bool) throws(JSException) -> Void " @@ -282,7 +282,7 @@ exports[`ts2swift > snapshots Swift output for PrimitiveReturn.d.ts > PrimitiveR // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func checkNumber() throws(JSException) -> Double @@ -297,7 +297,7 @@ exports[`ts2swift > snapshots Swift output for ReExportFrom.d.ts > ReExportFrom // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func jsRoundTripNumber(_ v: Double) throws(JSException) -> Double @@ -315,7 +315,7 @@ exports[`ts2swift > snapshots Swift output for RecordDictionary.d.ts > RecordDic // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func takeRecord(_ value: [String: Double]) throws(JSException) -> Void @@ -345,7 +345,7 @@ exports[`ts2swift > snapshots Swift output for StringEnum.d.ts > StringEnum 1`] // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit enum FeatureFlag: String { case foo = "foo" @@ -366,7 +366,7 @@ exports[`ts2swift > snapshots Swift output for StringParameter.d.ts > StringPara // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func checkString(_ a: String) throws(JSException) -> Void @@ -381,7 +381,7 @@ exports[`ts2swift > snapshots Swift output for StringReturn.d.ts > StringReturn // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func checkString() throws(JSException) -> String " @@ -394,7 +394,7 @@ exports[`ts2swift > snapshots Swift output for TS2SkeletonLike.d.ts > TS2Skeleto // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func createTS2Skeleton() throws(JSException) -> TypeScriptProcessor @@ -420,7 +420,7 @@ exports[`ts2swift > snapshots Swift output for TypeAlias.d.ts > TypeAlias 1`] = // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func checkSimple(_ a: Double) throws(JSException) -> Void " @@ -433,7 +433,7 @@ exports[`ts2swift > snapshots Swift output for TypeAliasObject.d.ts > TypeAliasO // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func console() throws(JSException) -> Console @@ -452,7 +452,7 @@ exports[`ts2swift > snapshots Swift output for TypeScriptClass.d.ts > TypeScript // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSClass struct Greeter { @JSGetter var name: String @@ -473,7 +473,7 @@ exports[`ts2swift > snapshots Swift output for VoidParameterVoidReturn.d.ts > Vo // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func check() throws(JSException) -> Void " @@ -486,7 +486,7 @@ exports[`ts2swift > snapshots Swift output for WebIDLDOMDocs.d.ts > WebIDLDOMDoc // To update this file, just rebuild your project or run // \`swift package bridge-js\`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit /// [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document) @JSGetter var document: Document diff --git a/Plugins/PackageToJS/Sources/PackageToJS.swift b/Plugins/PackageToJS/Sources/PackageToJS.swift index 268f3f200..2e47dcf71 100644 --- a/Plugins/PackageToJS/Sources/PackageToJS.swift +++ b/Plugins/PackageToJS/Sources/PackageToJS.swift @@ -589,11 +589,6 @@ struct PackagingPlanner { packageInputs.append(packageJsonTask) if skeletons.count > 0 { - if ProcessInfo.processInfo.environment["JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS"] == nil { - fatalError( - "BridgeJS is still an experimental feature. Set the environment variable JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 to enable." - ) - } let bridgeJs = outputDir.appending(path: "bridge-js.js") let bridgeDts = outputDir.appending(path: "bridge-js.d.ts") packageInputs.append( diff --git a/README.md b/README.md index 6a0acaa27..b5cb04801 100644 --- a/README.md +++ b/README.md @@ -48,14 +48,14 @@ _ = document.body.appendChild(button) BridgeJS provides easy interoperability between Swift and JavaScript/TypeScript. It enables: -- **Exporting Swift APIs to JavaScript**: Make your Swift code callable from JavaScript -- **Importing TypeScript APIs into Swift**: Use JavaScript APIs with type safety in Swift +- **Export Swift to JavaScript** – Expose Swift functions, classes, and types to JavaScript; the plugin also generates TypeScript definitions (`.d.ts`) for the exported API. +- **Import JavaScript into Swift** – Make JavaScript/TypeScript APIs (functions, classes, globals like `document` or `console`) callable from Swift with type-safe bindings. You can declare bindings with macros in Swift or generate them from a TypeScript declaration file (`bridge-js.d.ts`). -For architecture details, see the [BridgeJS Plugin README](Plugins/BridgeJS/README.md). +For architecture details, see the [BridgeJS Plugin README](Plugins/BridgeJS/README.md). For package and build setup, see [Setting up BridgeJS](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/setting-up-bridgejs) in the documentation. ### Exporting Swift to JavaScript -Mark Swift code with `@JS` to make it callable from JavaScript: +Mark Swift code with `@JS` (the ``JS(namespace:enumStyle:)`` attribute) to make it callable from JavaScript: ```swift import JavaScriptKit @@ -81,32 +81,36 @@ console.log(greeter.greet()); // "Hello, World!" **Learn more:** [Exporting Swift to JavaScript](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/exporting-swift-to-javascript) -### Importing TypeScript into Swift +### Importing JavaScript into Swift -Define TypeScript interfaces and BridgeJS generates type-safe Swift bindings: +Declare bindings in Swift with macros such as `@JSFunction`, `@JSClass`, `@JSGetter`, and `@JSSetter`: -```typescript -// bridge-js.d.ts -interface Document { - title: string; - getElementById(id: string): HTMLElement; - createElement(tagName: string): HTMLElement; +```swift +import JavaScriptKit + +@JSClass struct Document { + @JSFunction func getElementById(_ id: String) throws(JSException) -> HTMLElement + @JSFunction func createElement(_ tagName: String) throws(JSException) -> HTMLElement } +@JSGetter(from: .global) var document: Document -export function getDocument(): Document; -``` +@JSClass struct HTMLElement { + @JSGetter var innerText: String + @JSSetter func setInnerText(_ newValue: String) throws(JSException) + @JSFunction func appendChild(_ child: HTMLElement) throws(JSException) +} -**Swift usage:** -```swift @JS func run() throws(JSException) { - let document = try getDocument() - try document.setTitle("My Swift App") - let button = try document.createElement("button") + let button = document.createElement("button")! try button.setInnerText("Click Me") + let container = document.getElementById("app")! + container.appendChild(button) } ``` -**Learn more:** [Importing TypeScript into Swift](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/importing-typescript-into-swift) +You can also generate the same macro-annotated Swift from a TypeScript file (`bridge-js.d.ts`). See [Generating bindings from TypeScript](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/generating-from-typescript) in the documentation. + +**Learn more:** [Importing JavaScript into Swift](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/importing-javascript-into-swift) ### Try It Online diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Ahead-of-Time-Code-Generation.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Ahead-of-Time-Code-Generation.md index ee6ac3047..776f6f577 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Ahead-of-Time-Code-Generation.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Ahead-of-Time-Code-Generation.md @@ -6,7 +6,7 @@ Learn how to improve build times by generating BridgeJS code ahead of time. > Important: This feature is still experimental. No API stability is guaranteed, and the API may change in future releases. -The BridgeJS build plugin automatically processes `@JS` annotations and TypeScript definitions during each build. While convenient, this can significantly increase build times for larger projects. To address this, JavaScriptKit provides a command plugin that lets you generate the bridge code ahead of time. +The BridgeJS build plugin automatically processes macro annotations and TypeScript definitions during each build. While convenient, this can significantly increase build times for larger projects. To address this, JavaScriptKit provides a command plugin that lets you generate the bridge code ahead of time. ## Using the Command Plugin @@ -54,7 +54,7 @@ $ echo "{}" > Sources/MyApp/bridge-js.config.json ### Step 3: Create Your Swift Code with @JS Annotations -Write your Swift code with `@JS` annotations as usual: +Write your Swift code with macro annotations as usual: ```swift import JavaScriptKit @@ -65,13 +65,13 @@ import JavaScriptKit @JS class Counter { private var count = 0 - + @JS init() {} - + @JS func increment() { count += 1 } - + @JS func getValue() -> Int { return count } @@ -104,14 +104,15 @@ swift package plugin bridge-js This command will: -1. Process all Swift files with `@JS` annotations +1. Process all Swift files with macro annotations 2. Process any TypeScript definition files 3. Generate Swift binding code in a `Generated` directory within your source folder For example, with a target named "MyApp", it will create: ``` -Sources/MyApp/Generated/BridgeJS.swift # Generated code for both exports and imports +Sources/MyApp/Generated/BridgeJS.swift # Glue code for both exports and imports +Sources/MyApp/Generated/BridgeJS.Macros.swift # Bridging interface generated from bridge-js.d.ts Sources/MyApp/Generated/JavaScript/BridgeJS.json # Unified skeleton JSON ``` @@ -173,4 +174,4 @@ git commit -m "Update generated BridgeJS code" 2. **Version Control**: Always commit the generated files if using the command plugin 3. **API Boundaries**: Try to stabilize your API boundaries to minimize regeneration 4. **Documentation**: Document your approach in your project README -5. **CI/CD**: If using the command plugin, consider verifying that generated code is up-to-date in CI +5. **CI/CD**: If using the command plugin, consider verifying that generated code is up-to-date in CI diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Configuration.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Configuration.md index 78b5d2d37..604017aad 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Configuration.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Configuration.md @@ -42,7 +42,7 @@ Later files override settings from earlier files. This allows teams to commit a Controls whether exported Swift APIs are exposed to the JavaScript global namespace (`globalThis`). -When `true`, exported functions, classes, and namespaces are available via `globalThis` in JavaScript. When `false`, they are only available through the exports object returned by `createExports()`. +When `true`, exported functions, classes, and namespaces are available via `globalThis` in JavaScript. When `false`, they are only available through the exports object returned by `createExports()`. Using Exports provides better module isolation and support multiple WebAssembly instances in the same JavaScript context. Example: diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Internals/BridgeJS-Internals.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Internals/BridgeJS-Internals.md new file mode 100644 index 000000000..b8589b49e --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Internals/BridgeJS-Internals.md @@ -0,0 +1,11 @@ +# BridgeJS Internals + +Internal design, performance rationale, and low-level details for BridgeJS. + +## Overview + +This section is for maintainers and contributors who want to understand how BridgeJS works under the hood, why it is designed the way it is, and how it interacts with the JavaScript engine and ABI. + +## Topics + +- diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Internals/Design-Rationale.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Internals/Design-Rationale.md new file mode 100644 index 000000000..8bfc5d302 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Internals/Design-Rationale.md @@ -0,0 +1,38 @@ +# BridgeJS Design Rationale + +Why BridgeJS is faster than dynamic `JSObject`/`JSValue` APIs and how engine optimizations influence the design. + +## Overview + +BridgeJS generates **specialized** bridge code per exported or imported interface. That specialization, combined with stable call and property access patterns, allows JavaScript engines to optimize the boundary crossing much better than with generic dynamic code. This page explains the main performance rationale. + +## Why generated code is faster + +1. **Specialized code per interface** - Each bridged function or property gets its own glue path with known types. The engine does not need to handle arbitrary shapes or types at the call site. + +2. **Use of static type information** - The generator knows parameter and return types at compile time. It can avoid dynamic type checks and boxing where the dynamic API would require them. + +3. **IC-friendly access patterns** - Property and method accesses use stable, predictable shapes instead of a single generic subscript path. That keeps engine **inline caches (ICs)** effective instead of turning them **megamorphic**. + +## Inline caches (ICs) and megamorphic penalty + +JavaScript engines (and many other dynamic-language VMs) use **inline caches** at property and method access sites: they remember the object shape (e.g. “this property is at offset X”) so the next access with the same shape can take a fast path. + +- **Monomorphic** - One shape seen at a site → very fast, offset cached. +- **Polymorphic** - A few shapes → still fast, small dispatch in the IC. +- **Megamorphic** - Too many different shapes at the same site → the IC gives up and falls back to a generic property lookup, which is much slower. + +Engines typically allow only a small number of shapes per IC (e.g. on the order of a few) before marking the site megamorphic. + +## Why `JSObject` subscript is problematic + +`JSObject.subscript` (and similar dynamic property access) shares **one** code path for all property names and all object shapes. Every access goes through the same call site with varying keys and receiver shapes. That site therefore sees many different shapes and quickly becomes **megamorphic**, so the engine cannot cache property offsets and must do a generic lookup every time. + +So even if you cache the property name (e.g. with `CachedJSStrings`), you are still using the same generic subscript path; the call site stays megamorphic and pays the slow-path cost. + +BridgeJS avoids this by generating **separate** access paths per property or method. Each generated getter/setter or function call has a stable shape at the engine level, so the IC can stay monomorphic or polymorphic and the fast path is used. + +## What to read next + +- ABI and binary interface details will be documented in this section as they stabilize. +- For using BridgeJS in your app, see , , and . diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Bringing-Swift-Closures-to-JavaScript.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Bringing-Swift-Closures-to-JavaScript.md new file mode 100644 index 000000000..ce1d9d555 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Bringing-Swift-Closures-to-JavaScript.md @@ -0,0 +1,80 @@ +# Bringing Swift Closures to JavaScript + +Use ``JSTypedClosure`` to pass or return Swift closures to the JavaScript world with BridgeJS-with type safety and explicit lifetime management. + +## Overview + +``JSTypedClosure`` wraps a **Swift closure** so you can **pass it or return it to JavaScript** through BridgeJS. The closure lives in Swift; JavaScript receives a function that calls back into that closure when invoked. Use it when: + +- You **pass** a Swift closure as an argument to a JavaScript API (e.g. an ``JSFunction(jsName:from:)`` that takes a callback parameter). +- You **return** a Swift closure from Swift exported by ``JS(namespace:enumStyle:)`` so JavaScript can call it later. + +Unlike ``JSClosure``, which uses untyped ``JSValue`` arguments and return values, ``JSTypedClosure`` has a concrete **signature** (e.g. `(Int) -> Int` or `(String) -> Void`). BridgeJS generates the glue code for that signature, so you get compile-time type safety when crossing into the JS world. + +You **must call** ``JSTypedClosure/release()`` when the closure is no longer needed by JavaScript. After release, any attempt to invoke the closure from JavaScript throws an explicit JS exception. + +## Creating a JSTypedClosure + +BridgeJS generates an initializer for each closure signature used in your module. Wrap your Swift closure and pass or return it to JavaScript: + +```swift +import JavaScriptKit + +// Pass a Swift closure to a JS function that expects a callback (Int) -> Int +@JSFunction static func applyTransform(_ value: Int, _ transform: JSTypedClosure<(Int) -> Int>) throws(JSException) -> Int + +let double = JSTypedClosure<(Int) -> Int> { $0 * 2 } +defer { double.release() } +let result = try applyTransform(10, double) // 20 - JS calls back into Swift +``` + +You can pass or return typed closures with other signatures the same way: + +```swift +let sum = JSTypedClosure<(Int, Int) -> Int> { $0 + $1 } +defer { sum.release() } + +let log = JSTypedClosure<(String) -> Void> { print($0) } +defer { log.release() } +``` + +## Lifetime and release() + +A ``JSTypedClosure`` keeps the Swift closure alive and exposes a JavaScript function that calls into it. To avoid leaks and use-after-free: + +1. **Call `release()` exactly once** when the closure is no longer needed by JavaScript (e.g. when the callback is unregistered or the object that held it is released). +2. Prefer **`defer { closure.release() }`** right after creating the closure so cleanup runs when the current scope exits. +3. After `release()`, calling the closure from JavaScript throws an exception with a message that includes the file and line where the ``JSTypedClosure`` was created. + +A **FinalizationRegistry** on the JavaScript side may eventually release the Swift storage if you never call `release()`, but that is non-deterministic. Do not rely on it for timely cleanup. + +## Getting the underlying JavaScript function + +When you need to store or pass the function on the JavaScript side (e.g. to compare identity or attach to a DOM node), use the ``JSTypedClosure/jsObject`` property to get the ``JSObject`` that represents the JavaScript function. + +## JSTypedClosure vs JSClosure + +Both let you pass or return a Swift closure to the JavaScript world. The difference is how they are typed and which API you use: + +| | JSTypedClosure | JSClosure | +|:--|:--|:--| +| **API** | BridgeJS (macros, generated code) | Dynamic ``JSObject`` / ``JSValue`` | +| **Types** | Typed signature, e.g. `(Int) -> Int` | Untyped `([JSValue]) -> JSValue` | +| **Lifetime** | Explicit `release()` required | Explicit `release()` required | +| **Use case** | Passing/returning closures at the BridgeJS boundary with a fixed signature | Passing Swift functions to JS via dynamic APIs (e.g. DOM events) | + +Use ``JSTypedClosure`` when you pass or return closures through BridgeJS-declared APIs. Use ``JSClosure`` when you pass a Swift function to JavaScript using the dynamic APIs (e.g. ``JSObject``, ``JSValue``) without generated glue. + +## JSTypedClosure vs auto-managed closures + +BridgeJS can also expose **plain** Swift closure types (e.g. `(String) -> String`) as parameters and return values; lifetime is then managed automatically via ``FinalizationRegistry`` and no `release()` is required. See . + +**When returning** a closure from Swift to JavaScript, we **recommend** using ``JSTypedClosure`` and managing lifetime explicitly with `release()`, rather than returning a plain closure type. Explicit release makes cleanup predictable and avoids relying solely on JavaScript GC. + +## See also + +- ``JSTypedClosure`` +- ``JSClosure`` +- +- +- diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md index 75f0fcca5..b14d2eebe 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md @@ -6,60 +6,11 @@ Learn how to make your Swift code callable from JavaScript. > Important: This feature is still experimental. No API stability is guaranteed, and the API may change in future releases. -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). - -BridgeJS allows you to expose Swift functions, classes, and methods to JavaScript by using the `@JS` attribute. This enables JavaScript code to call into Swift code running in WebAssembly. - -## Configuring the BridgeJS plugin - -To use the BridgeJS feature, you need to enable the experimental `Extern` feature and add the BridgeJS plugin to your package. Here's an example of a `Package.swift` file: - -```swift -// swift-tools-version:6.0 - -import PackageDescription - -let package = Package( - name: "MyApp", - dependencies: [ - .package(url: "https://github.com/swiftwasm/JavaScriptKit.git", branch: "main") - ], - targets: [ - .executableTarget( - name: "MyApp", - dependencies: ["JavaScriptKit"], - swiftSettings: [ - // This is required because the generated code depends on @_extern(wasm) - .enableExperimentalFeature("Extern") - ], - plugins: [ - // Add build plugin for processing @JS and generate Swift glue code - .plugin(name: "BridgeJS", package: "JavaScriptKit") - ] - ) - ] -) -``` - -The `BridgeJS` plugin will process your Swift code to find declarations marked with `@JS` and generate the necessary bridge code to make them accessible from JavaScript. - -### Building your package for JavaScript - -After configuring your `Package.swift`, you can build your package for JavaScript using the following command: - -```bash -swift package --swift-sdk $SWIFT_SDK_ID js -``` - -This command will: - -1. Process all Swift files with `@JS` annotations -2. Generate JavaScript bindings and TypeScript type definitions (`.d.ts`) for your exported Swift code -3. Output everything to the `.build/plugins/PackageToJS/outputs/` directory - -> Note: For larger projects, you may want to generate the BridgeJS code ahead of time to improve build performance. See for more information. +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). +BridgeJS allows you to expose Swift functions, classes, and methods to JavaScript by using the ``JS(namespace:enumStyle:)`` attribute. This enables JavaScript code to call into Swift code running in WebAssembly. +Configure your package and build for JavaScript as described in . Then use the topics below to expose Swift types and functions to JavaScript. ## Topics @@ -75,3 +26,7 @@ This command will: - - - + +## See Also + +- ``JS(namespace:enumStyle:)`` diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Array.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Array.md index 53d008068..e97bceefa 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Array.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Array.md @@ -4,7 +4,7 @@ Learn how to pass Swift arrays to and from JavaScript. ## Overview -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). BridgeJS allows you to pass Swift arrays as function parameters and return values. diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Class.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Class.md index 3e44581fa..9cd4a2224 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Class.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Class.md @@ -4,7 +4,7 @@ Learn how to export Swift classes to JavaScript. ## Overview -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). To export a Swift class, mark both the class and any members you want to expose: @@ -51,6 +51,7 @@ cart.addItem("Laptop", 999.99, 1); cart.addItem("Mouse", 24.99, 2); console.log(`Items in cart: ${cart.getItemCount()}`); console.log(`Total: $${cart.getTotal().toFixed(2)}`); +cart.release(); // Call release() when done; don't rely on FinalizationRegistry as much as possible ``` The generated TypeScript declarations for this class would look like: @@ -83,7 +84,7 @@ Classes use **reference semantics** when crossing the Swift/JavaScript boundary: 1. **Object Creation**: When you create a class instance (via `new` in JS), the object lives on the Swift heap 2. **Reference Passing**: JavaScript receives a reference (handle) to the Swift object, not a copy 3. **Shared State**: Changes made through either Swift or JavaScript affect the same object -4. **Memory Management**: `FinalizationRegistry` automatically releases Swift objects when they're garbage collected in JavaScript. You can optionally call `release()` for deterministic cleanup. +4. **Memory Management**: `FinalizationRegistry` can release Swift objects when they're garbage collected in JavaScript, but you should **not rely on it** for cleanup. Call `release()` when an instance is no longer needed so that Swift memory is reclaimed deterministically. This is especially important for **short-lived instances**: GC may run late or not at all for objects that become unreachable quickly, so relying on `FinalizationRegistry` can delay or leak Swift-side resources. This differs from structs, which use copy semantics and transfer data by value. diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Closure.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Closure.md index fe934ddba..adb9ab33b 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Closure.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Closure.md @@ -4,9 +4,11 @@ Learn how to use closure/function types as parameters and return values in Bridg ## Overview -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). -BridgeJS supports typed closure parameters and return values, allowing you to pass functions between Swift and JavaScript with full type safety. This enables functional programming patterns like callbacks, higher-order functions, and function composition across the language boundary. +BridgeJS supports typed closure parameters and return values, allowing you to pass or return Swift closures to JavaScript with full type safety. **Lifetime is automatic**: you use plain Swift closure types (e.g. `(String) -> String`); the runtime releases them when no longer needed-no manual `release()` required. This enables callbacks, higher-order functions, and function composition across the boundary. + +**Recommendation:** When **returning** a closure from Swift to JavaScript, prefer returning a ``JSTypedClosure`` and managing its lifetime explicitly (see ). Explicit `release()` makes cleanup predictable and avoids relying solely on JavaScript garbage collection. Use plain closure types (this article) when you want fully automatic lifetime or when passing closures only as parameters into your exported API. ## Example @@ -99,6 +101,8 @@ Closures use **reference semantics** when crossing the Swift/JavaScript boundary This differs from structs and arrays, which use copy semantics and transfer data by value. +When you **return** a closure to JavaScript, we recommend using ``JSTypedClosure`` and calling `release()` when the closure is no longer needed, instead of returning a plain closure type. See . + ## Supported Features | Swift Feature | Status | @@ -113,4 +117,5 @@ This differs from structs and arrays, which use copy semantics and transfer data ## See Also +- - passing or returning closures with ``JSTypedClosure`` and explicit `release()` - diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Default-Parameters.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Default-Parameters.md index f6115f063..e6f4b8e9a 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Default-Parameters.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Default-Parameters.md @@ -4,7 +4,7 @@ Learn how to use default parameter values in Swift functions and constructors ex ## Overview -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). BridgeJS supports default parameter values for Swift functions and class constructors exported to JavaScript. When you specify default values in your Swift code, they are automatically applied in the generated JavaScript bindings. @@ -64,7 +64,7 @@ Constructor parameters also support default values, making it easy to create ins @JS var name: String @JS var timeout: Int @JS var retries: Int - + @JS init(name: String = "default", timeout: Int = 30, retries: Int = 3) { self.name = name self.timeout = timeout diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Enum.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Enum.md index 6fb3afeda..2220d457c 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Enum.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Enum.md @@ -4,7 +4,7 @@ Learn how to export Swift enums to JavaScript. ## Overview -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). BridgeJS supports two output styles for enums, controlled by the `enumStyle` parameter: diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Function.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Function.md index ebc8037c4..c26841041 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Function.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Function.md @@ -4,7 +4,7 @@ Learn how to export Swift functions to JavaScript. ## Overview -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). To export a Swift function to JavaScript, mark it with the `@JS` attribute and make it `public`: diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Optional.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Optional.md index 91fdc3472..be15b762f 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Optional.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Optional.md @@ -4,14 +4,12 @@ Learn how to use Swift optionals in functions, classes, and enums exported to Ja ## Overview -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). BridgeJS provides comprehensive support for Swift optionals across all bridged types. When you use `Optional` or `T?` in Swift, it automatically maps to `T | null` in TypeScript/JavaScript. Swift optionals are translated to union types with `null` (not `undefined`) because `null` represents an explicit "no value" state that aligns semantically with Swift's `nil`. This design choice ensures consistent null handling across the Swift-JavaScript bridge and avoids the ambiguity that comes with JavaScript's `undefined`. -> Important: BridgeJS optional support is **Swift → JavaScript only**. TypeScript → Swift optional imports are not currently supported. - ## Supported Optional Syntax BridgeJS recognizes all Swift optional syntax variants: @@ -35,7 +33,7 @@ All parameter types can be made optional, including primitives, objects, and enu ```swift @JS public func processOptionalData( text: String?, // Optional string - count: Int?, // Optional integer + count: Int?, // Optional integer flag: Bool?, // Optional boolean rate: Double?, // Optional double user: User? // Optional Swift class @@ -85,7 +83,7 @@ Constructors can accept optional parameters. @JS public var email: String? @JS public var age: Int? @JS public var avatar: User? - + @JS public init(name: String?) @JS public func updateProfile(email: String?, age: Int?) } @@ -100,7 +98,7 @@ export interface UserProfile extends SwiftHeapObject { email: string | null; age: number | null; avatar: User | null; - + updateProfile(email: string | null, age: number | null): void; } export type UserProfile = { diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Protocols.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Protocols.md index 111b1f052..3b2ec1526 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Protocols.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Protocols.md @@ -4,7 +4,7 @@ Learn how to expose Swift protocols to JavaScript as TypeScript interfaces. ## Overview -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). BridgeJS allows you to export Swift protocols as TypeScript interfaces. JavaScript objects implementing these interfaces can be passed to Swift code, enabling protocol-oriented design across the Swift-JavaScript boundary. @@ -31,28 +31,28 @@ import JavaScriptKit @JS class CounterManager { var delegate: Counter - + @JS init(delegate: Counter) { self.delegate = delegate } - + @JS func incrementTwice() { delegate.increment(by: 1) delegate.increment(by: 1) } - + @JS func getCurrentValue() -> Int { return delegate.getValue() } - + @JS func getCounterName() -> String { return delegate.name } - + @JS func setCountValue(_ value: Int) { delegate.count = value } - + @JS func updateLabel(_ newLabel: String?) { delegate.label = newLabel } @@ -130,15 +130,15 @@ You can also implement protocols in Swift and use them from JavaScript: final class SwiftCounter: Counter { var count = 0 let name = "SwiftCounter" - + func increment(by amount: Int) { count += amount } - + func reset() { count = 0 } - + func getValue() -> Int { return count } diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Functions.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Functions.md index b6f680d1f..1c4b22abe 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Functions.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Functions.md @@ -4,7 +4,7 @@ Learn how to export Swift static and class functions as JavaScript static method ## Overview -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). BridgeJS supports exporting Swift `static func` and `class func` to JavaScript static methods. Both generate identical JavaScript output but differ in Swift inheritance behavior. @@ -17,15 +17,15 @@ Classes can export both `static` and `class` functions: ```swift @JS class MathUtils { @JS init() {} - + @JS static func add(a: Int, b: Int) -> Int { return a + b } - + @JS class func subtract(a: Int, b: Int) -> Int { return a - b } - + @JS func multiply(x: Int, y: Int) -> Int { return x * y } @@ -79,11 +79,11 @@ Enums can contain static functions that are exported as properties: @JS enum Calculator { case scientific case basic - + @JS static func square(value: Int) -> Int { return value * value } - + @JS static func cube(value: Int) -> Int { return value * value * value } diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Properties.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Properties.md index 4110e6166..4898535c8 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Properties.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Properties.md @@ -4,7 +4,7 @@ Learn how to export Swift static and class properties as JavaScript static prope ## Overview -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). BridgeJS supports exporting Swift `static var`, `static let`, and `class var` properties to JavaScript static properties. Both stored and computed properties are supported. @@ -15,16 +15,16 @@ Classes can export both stored and computed static properties: ```swift @JS class Configuration { @JS init() {} - + @JS static let version = "1.0.0" @JS static var debugMode = false @JS class var defaultTimeout = 30 - + @JS static var timestamp: Double { get { return Date().timeIntervalSince1970 } set { /* custom setter logic */ } } - + @JS static var buildNumber: Int { return 12345 } @@ -81,7 +81,7 @@ Enums can contain static properties that are exported alongside enum cases: @JS enum PropertyEnum { case value1 case value2 - + @JS static var enumProperty = "mutable" @JS static let enumConstant = 42 @JS static var computedEnum: String { diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Struct.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Struct.md index 10babd9b6..32bb79ed3 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Struct.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Struct.md @@ -4,7 +4,7 @@ Learn how to export Swift structs to JavaScript. ## Overview -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). To export a Swift struct, mark it with `@JS`: @@ -91,7 +91,7 @@ export type Exports = { ```swift @JS struct Config { var name: String - + @JS nonisolated(unsafe) static var defaultTimeout: Double = 30.0 @JS static let maxRetries: Int = 3 } diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Using-Namespace.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Using-Namespace.md index 057b5f030..1aff82f65 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Using-Namespace.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Using-Namespace.md @@ -4,7 +4,7 @@ Learn how to organize exported Swift code into JavaScript namespaces. ## Overview -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). The `@JS` macro supports organizing your exported Swift code into namespaces using dot-separated strings. This allows you to create hierarchical structures in JavaScript that mirror your Swift code organization. @@ -121,7 +121,3 @@ export interface Greeter extends SwiftHeapObject { ``` Using namespaces can be preferable for projects with many global functions, as they help prevent naming collisions. Namespaces also provide intuitive hierarchies for organizing your exported Swift code, and they do not affect the code generated by `@JS` declarations without namespaces. - -## See Also - -- - Namespace enums section diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Generating-from-TypeScript.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Generating-from-TypeScript.md new file mode 100644 index 000000000..9c0a80dc1 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Generating-from-TypeScript.md @@ -0,0 +1,419 @@ +# Generating bindings from TypeScript + +How to generate macro-annotated Swift bindings from a TypeScript declaration file (`bridge-js.d.ts`) so you don't have to write the Swift by hand. + +## Overview + +The BridgeJS plugin can read a `bridge-js.d.ts` file in your target and generate Swift code that uses the same macros as hand-written bindings (see ). + +The output is macro-annotated Swift; you can inspect the generated file at the following path to see exactly what was produced: + +``` +./build/plugins/outputs///destination/BridgeJS/BridgeJS.Macros.swift +``` + +Use this workflow when you have existing TypeScript definitions or many APIs to bind. + +> Important: This feature is still experimental. No API stability is guaranteed, and the API may change in future releases. + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +## How to generate bindings from TypeScript + +### Step 1: Configure your package + +Add the BridgeJS plugin and enable the Extern feature as described in . + +### Step 2: Create TypeScript definitions + +Create a file named `bridge-js.d.ts` in your target source directory (e.g. `Sources//bridge-js.d.ts`). Declare the JavaScript APIs you want to use in Swift: + +```typescript +export function consoleLog(message: string): void; +``` + +### Step 3: Build your package + +Run: + +```bash +swift package --swift-sdk $SWIFT_SDK_ID js +``` + +The plugin processes `bridge-js.d.ts`, generates Swift bindings (using the same macros as in ), compiles to WebAssembly, and produces JavaScript glue in `.build/plugins/PackageToJS/outputs/`. + +> Note: For larger projects, see . + +## Declaration mappings + +### Functions + +Each exported function becomes a top-level Swift function with `@JSFunction` and `throws(JSException)`. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + + /** Returns the sum of two numbers. */ + export function sum(a: number, b: number): number; + /** + * Sets the document title. + * @param title - The new title string + */ + export function setDocumentTitle(title: string): void; + ``` + } + @Column { + ```swift + // Generated Swift + + /// Returns the sum of two numbers. + @JSFunction func sum(a: Double, b: Double) throws(JSException) -> Double + + + /// Sets the document title. + /// - Parameter title: The new title string + @JSFunction func setDocumentTitle(title: String) throws(JSException) + ``` + } +} + +### Global getters + +Module-level `declare const` or top-level readonly bindings that reference a bridged type become a Swift global property with `@JSGetter`. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document) */ + export const document: Document; + ``` + } + @Column { + ```swift + // Generated Swift + /// [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document) + @JSGetter var document: Document + ``` + } +} + +### Classes + +A class becomes a Swift struct with `@JSClass`. The constructor becomes `init(...)` with `@JSFunction`. Properties become `@JSGetter`; writable properties also get `@JSSetter` as `set(_:)`. Methods become `@JSFunction`. Static methods become `static func` on the struct. All thunks throw `JSException` if the underlying JavaScript throws. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + export class Greeter { + /** A readonly field is translated with `@JSGetter` */ + readonly id: number; + + /** A read-writable field is translated with `@JSGetter` and `@JSSetter` */ + message: string; + + /** A constructor */ + constructor(id: string, name: string); + /** A method */ + greet(): string; + /** A static method */ + static createDefault(greetingId: number, locale: string): string; + } + ``` + } + @Column { + ```swift + // Generated Swift + @JSClass struct Greeter { + /// A readonly field is translated with `@JSGetter` + @JSGetter var id: Double + + /// A read-writable field is translated with `@JSGetter` and `@JSSetter` + @JSGetter var message: String + @JSSetter func setMessage(_ newValue: String) throws(JSException) + + /// A constructor + @JSFunction init(id: String, name: String) throws(JSException) + /// A method + @JSFunction func greet() throws(JSException) -> String + @JSFunction static func createDefault(_ greetingId: Double, _ locale: String) throws(JSException) -> String + } + ``` + } +} + +### Interfaces + +An interface becomes a Swift struct with `@JSClass`. No constructor. Properties and methods are bridged the same way as for classes (`@JSGetter`, `@JSSetter`, `@JSFunction`). Instances are obtained from other calls (e.g. a function that returns the interface type). + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + export interface HTMLElement { + readonly innerText: string; + className: string; + + appendChild(child: HTMLElement): void; + } + ``` + } + @Column { + ```swift + // Generated Swift + @JSClass struct HTMLElement { + @JSGetter var innerText: String + @JSGetter var className: String + @JSSetter func setClassName(_ newValue: String) throws(JSException) + @JSFunction func appendChild(_ child: HTMLElement) throws(JSException) + } + ``` + } +} + +### Type aliases + +Type aliases are resolved when generating Swift; the resolved shape is emitted, not a separate alias type. + +- **Primitive alias** (e.g. `type UserId = string`): Replaced by the underlying Swift type (e.g. `String`) everywhere it is used. +- **Object-shaped alias** (e.g. `type User = { id: string; name: string }`): The generator emits a named Swift struct with that name and the corresponding `@JSClass` / getters / setters. No constructor; use is the same as for interfaces. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + export type UserId = string; + export type User = { + readonly id: UserId; + name: string; + }; + export function getUser(): User; + ``` + } + @Column { + ```swift + // Generated Swift (UserId inlined as String) + @JSClass struct User { + @JSGetter var id: String + @JSGetter var name: String + @JSSetter func setName(_ newValue: String) throws(JSException) + } + @JSFunction func getUser() throws(JSException) -> User + ``` + } +} + +### String enums + +TypeScript enums with string literal values become Swift enums with `String` raw value and the appropriate BridgeJS protocol conformances. Usable as parameter and return types. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + export enum Theme { + light = "light", + dark = "dark", + } + + + export function setTheme(theme: Theme): void; + export function getTheme(): Theme; + ``` + } + @Column { + ```swift + // Generated Swift + enum Theme: String { + case light = "light" + case dark = "dark" + } + extension Theme: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum {} + + @JSFunction func setTheme(_ theme: Theme) throws(JSException) -> Void + @JSFunction func getTheme() throws(JSException) -> Theme + ``` + } +} + +## Type mappings + +The following mappings apply to function parameters, return types, and class/interface properties. + +### Primitives + +| TypeScript | Swift | +|------------|-------| +| `number` | `Double` | +| `string` | `String` | +| `boolean` | `Bool` | + +These appear in the function and class examples above. + +### Arrays + +`T[]` and `Array` → `[T]`. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + export function sumAll(values: number[]): number; + export function getScores(): number[]; + export function getLabels(): string[]; + export function normalize(values: Array): Array; + ``` + } + @Column { + ```swift + // Generated Swift + @JSFunction func sumAll(_ values: [Double]) throws(JSException) -> Double + @JSFunction func getScores() throws(JSException) -> [Double] + @JSFunction func getLabels() throws(JSException) -> [String] + @JSFunction func normalize(_ values: [Double]) throws(JSException) -> [Double] + ``` + } +} + +### Optional and undefined + +- **`T | null`** → Swift `Optional` (e.g. `Optional`, `Optional`, `Optional`). +- **`T | undefined`** or optional parameters → Swift `JSUndefinedOr`. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + export function parseCount(value: number | null): number | null; + export function parseLimit(value: number | undefined): number | undefined; + export function scale(factor: number, offset: number | null): number; + + export interface Payload {} + export class RequestOptions { + body: Payload | null; + + headers: Payload | undefined; + + } + ``` + } + @Column { + ```swift + // Generated Swift + @JSFunction func parseCount(_ value: Optional) throws(JSException) -> Optional + @JSFunction func parseLimit(_ value: JSUndefinedOr) throws(JSException) -> JSUndefinedOr + @JSFunction func scale(_ factor: Double, _ offset: Optional) throws(JSException) -> Double + + @JSClass struct Payload {} + @JSClass struct RequestOptions { + @JSGetter var body: Optional + @JSSetter func setBody(_ value: Optional) throws(JSException) + @JSGetter var headers: JSUndefinedOr + @JSSetter func setHeaders(_ value: JSUndefinedOr) throws(JSException) + } + ``` + } +} + +### Records (dictionaries) + +`Record` → Swift `[String: V]`. Supported value types: primitives, arrays, nested records, optional object types. Keys other than `string` (e.g. `Record`) are unsupported; such parameters become `JSObject`. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + export function applyScores(scores: Record): void; + export function getMetadata(): Record; + export function getMatrix(value: Record>): Record>; + export function getSeries(values: Record): Record; + export function lookupByIndex(values: Record): void; + ``` + } + @Column { + ```swift + // Generated Swift + @JSFunction func applyScores(_ scores: [String: Double]) throws(JSException) -> Void + @JSFunction func getMetadata() throws(JSException) -> [String: String] + @JSFunction func getMatrix(_ value: [String: [String: Double]]) throws(JSException) -> [String: [String: Double]] + @JSFunction func getSeries(_ values: [String: [Double]]) throws(JSException) -> [String: [Double]] + @JSFunction func lookupByIndex(_ values: JSObject) throws(JSException) -> Void + ``` + } +} + +### Unbridged types (JSValue, JSObject) + +Types that cannot be expressed in the bridge (e.g. `any`, unsupported generics, or `Record`) are emitted as `JSValue` or `JSObject`. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + interface Animatable { + animate(keyframes: any, options: any): any; + } + export function getAnimatable(): Animatable; + ``` + } + @Column { + ```swift + // Generated Swift + @JSClass struct Animatable { + @JSFunction func animate(_ keyframes: JSValue, _ options: JSValue) throws(JSException) -> JSValue + } + @JSFunction func getAnimatable() throws(JSException) -> Animatable + ``` + } +} + +## Name mapping + +### Invalid or special property and type names + +When a TypeScript name is not a valid Swift identifier (e.g. contains dashes, spaces, or starts with a number), or is a Swift keyword, the generator emits a Swift-safe name and uses `jsName` so the JavaScript binding remains correct. Classes whose names start with `$` are prefixed with `_` in Swift and get `@JSClass(jsName: "...")`. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + interface DOMTokenList { + "data-attrib": number; + + "0": boolean; + + for: string; + + as(): void; + } + export class $jQuery { + "call-plugin"(): void; + } + ``` + } + @Column { + ```swift + // Generated Swift + @JSClass struct DOMTokenList { + @JSGetter(jsName: "data-attrib") var data_attrib: Double + @JSSetter(jsName: "data-attrib") func setData_attrib(_ value: Double) throws(JSException) + @JSGetter(jsName: "0") var _0: Bool + @JSSetter(jsName: "0") func set_0(_ value: Bool) throws(JSException) + @JSGetter var `for`: String + @JSSetter func setFor(_ value: String) throws(JSException) + @JSFunction func `as`() throws(JSException) -> Void + } + @JSClass(jsName: "$jQuery") struct _jQuery { + @JSFunction(jsName: "call-plugin") func call_plugin() throws(JSException) -> Void + } + ``` + } +} + +## Limitations + +- No first-class support for async/Promise-returning functions;. +- No generic type parameter can appear on a bridged function signature. \ No newline at end of file diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript-into-Swift.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript-into-Swift.md new file mode 100644 index 000000000..14fccbfc1 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript-into-Swift.md @@ -0,0 +1,98 @@ +# Importing JavaScript into Swift + +Learn how to make JavaScript APIs callable from your Swift code using macro-annotated bindings. + +## Overview + +> Important: This feature is still experimental. No API stability is guaranteed, and the API may change in future releases. + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +You can import JavaScript APIs into Swift in two ways: + +1. **Annotate Swift with macros** - Use `@JSFunction`, `@JSClass`, `@JSGetter`, and `@JSSetter` to declare bindings directly in Swift. No TypeScript required. Prefer this to get started. +2. **Generate bindings from TypeScript** - Use a `bridge-js.d.ts` file; the BridgeJS plugin generates the same macro-annotated Swift. See when you have existing `.d.ts` definitions or many APIs to bind. + +This guide covers the macro-based path. + +## How to import JavaScript APIs (macro path) + +### Step 1: Configure your package + +Add the BridgeJS plugin and enable the Extern feature as described in . + +### Step 2: Declare bindings in Swift with macros + +Create Swift declarations that mirror the JavaScript API you want to call. + +You can bring JavaScript into Swift in two ways: + +- **Inject at initialization**: Declare in Swift and supply the implementation in `getImports()` (e.g. a `today()` function). +- **Import from `globalThis`**: For APIs on the JavaScript global object (e.g. `console`, `document`), use `@JSGetter(from: .global)` so they are read from `globalThis` and you don't pass them in `getImports()`. + +```swift +import JavaScriptKit + +@JSFunction func today() -> String + +@JSClass struct JSConsole { + @JSFunction func log(_ message: String) throws(JSException) +} +@JSGetter(from: .global) var console: JSConsole + +@JSClass struct Document { + @JSFunction func getElementById(_ id: String) throws(JSException) -> HTMLElement + @JSFunction func createElement(_ tagName: String) throws(JSException) -> HTMLElement +} +@JSGetter(from: .global) var document: Document + +@JSClass struct HTMLElement { + @JSGetter var innerText: String + @JSSetter func setInnerText(_ newValue: String) throws(JSException) + @JSFunction func appendChild(_ child: HTMLElement) throws(JSException) +} +``` + +For full details, see , , and . + +### Step 3: Use the bindings in Swift + +Call the bound APIs from Swift: + +```swift +import JavaScriptKit + +@JS func run() { + try console.log("Hello from Swift! (\(today()))") + + let button = document.createElement("button")! + try button.setInnerText("Click Me") + let container = document.getElementById("app")! + container.appendChild(button) +} +``` + +### Step 5: Inject JavaScript implementations (if needed) + +Bindings imported from globalThis (e.g. `console`, `document`) are read at runtime and do not go in `getImports()`. Only APIs you inject at initialization must be supplied there: + +```javascript +// index.js +import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; + +const { exports } = await init({ + getImports() { + return { + today: () => new Date().toString() + }; + } +}); + +exports.run(); +``` + +## Topics + +- +- +- \ No newline at end of file diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Class.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Class.md new file mode 100644 index 000000000..4302e0e49 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Class.md @@ -0,0 +1,54 @@ +# Importing a JavaScript class or object into Swift + +This guide shows how to bind a JavaScript class (or object shape) so you can construct and use it from Swift with `@JSClass`. + +## Steps + +### 1. Declare a Swift struct with `@JSClass` + +Add a struct that mirrors the JavaScript class. Use `@JSFunction` for the initializer and for methods, and `@JSGetter` / `@JSSetter` for properties. Property setters are exposed as functions (e.g. `setMessage(_:)`) because Swift property setters cannot `throw`. + +```swift +import JavaScriptKit + +@JSClass struct Greeter { + @JSFunction init(id: String, name: String) throws(JSException) + + @JSGetter var id: String + @JSGetter var message: String + @JSSetter func setMessage(_ newValue: String) throws(JSException) + + @JSFunction func greet() throws(JSException) -> String +} +``` + +If the class is on `globalThis`, add `from: .global` to `@JSClass` and omit the type from `getImports()` in the next step. + +### 2. Wire the JavaScript side + +**If you chose injection:** Implement the class in JavaScript and pass it in `getImports()`. + +```javascript +// index.js +import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; + +class Greeter { + constructor(id, name) { /* ... */ } + get id() { /* ... */ } + get message() { /* ... */ } + set message(value) { /* ... */ } + greet() { /* ... */ } +} + +const { exports } = await init({ + getImports() { + return { Greeter }; + } +}); +``` + +**If you chose global:** Do not pass the class in `getImports()`; the runtime will resolve it from `globalThis`. + +## Macro options + +For optional parameters (`jsName`, `from`, etc.), see the API reference: ``JSClass(jsName:from:)``, ``JSFunction(jsName:from:)``, ``JSGetter(jsName:from:)``, and ``JSSetter(jsName:from:)``. diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Function.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Function.md new file mode 100644 index 000000000..64475acfa --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Function.md @@ -0,0 +1,51 @@ +# Importing a JavaScript function into Swift + +This guide shows how to bind a JavaScript function so it is callable from Swift using `@JSFunction`. + +## Steps + +### 1. Declare the function in Swift with `@JSFunction` + +Match the JavaScript name and signature. Use Swift types that bridge to the JS types you need (see ). + +```swift +import JavaScriptKit + +@JSFunction func add(_ a: Double, _ b: Double) throws(JSException) -> Double +@JSFunction func setTitle(_ title: String) throws(JSException) +``` + +To bind a function that lives on the JavaScript global object (e.g. `parseInt`, `setTimeout`), add `from: .global`. Use `jsName` when the Swift name differs from the JavaScript name - see the ``JSFunction(jsName:from:)`` API reference for options. + +### 2. Provide the implementation at initialization + +Return the corresponding function(s) in the object passed to `getImports()` when initializing the WebAssembly module. + +```javascript +// index.js +import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; + +const { exports } = await init({ + getImports() { + return { + add: (a, b) => a + b, + setTitle: (title) => { document.title = title }, + }; + } +}); +``` + +If you used `from: .global`, do not pass the function in `getImports()`; the runtime resolves it from `globalThis`. + +### 3. Handle errors + +Bound functions are `throws(JSException)`. Call them with `try` or `try?`; they throw when the JavaScript implementation throws. + +## Supported features + +| Feature | Status | +|:--|:--| +| Primitive parameter/result types (e.g. `Double`, `Bool`) | ✅ | +| `String` parameter/result type | ✅ | +| Async function | ❌ | +| Generics | ❌ | diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Variable.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Variable.md new file mode 100644 index 000000000..044ebbe52 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Variable.md @@ -0,0 +1,59 @@ +# Importing a global JavaScript variable into Swift + +This guide shows how to bind a JavaScript global variable (or any property you provide at initialization) so you can read and optionally write it from Swift using `@JSGetter` and `@JSSetter`. + +## Steps + +### 1. Declare the variable in Swift with `@JSGetter` + +Use a type that bridges to the JavaScript value (see ). For object-shaped values, use a struct conforming to the bridged type (e.g. a `@JSClass` struct). + +```swift +import JavaScriptKit + +@JSGetter(from: .global) var document: Document +@JSGetter(from: .global) var myConfig: String +``` + +To bind a variable that is not on `globalThis`, omit `from: .global` and supply the value in `getImports()` in the next step. Use `jsName` when the Swift name differs from the JavaScript property name - see the ``JSGetter(jsName:from:)`` API reference. + +### 2. Add a setter for writable variables (optional) + +If the JavaScript property is writable and you need to set it from Swift, add a corresponding `@JSSetter` function. Property setters are exposed as functions (e.g. `setMyConfig(_:)`) because Swift property setters cannot `throw`. + +```swift +@JSGetter(from: .global) var myConfig: String +@JSSetter(from: .global) func setMyConfig(_ newValue: String) throws(JSException) +``` + +### 3. Provide the value at initialization (injected only) + +If you did **not** use `from: .global`, pass the value in the object returned by `getImports()` when initializing the WebAssembly module. + +```javascript +// index.js +import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; + +const { exports } = await init({ + getImports() { + return { + myConfig: "production", + }; + } +}); +``` + +If you used `from: .global`, do not pass the variable in `getImports()`; the runtime reads it from `globalThis`. + +## Supported features + +| Feature | Status | +|:--|:--| +| Read-only global (e.g. `document`, `console`) | ✅ | +| Writable global | ✅ (`@JSSetter`) | +| Injected variable (via `getImports()`) | ✅ | + +## See also + +- ``JSGetter(jsName:from:)`` +- ``JSSetter(jsName:from:)`` diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript-into-Swift.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript-into-Swift.md deleted file mode 100644 index b091f714b..000000000 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript-into-Swift.md +++ /dev/null @@ -1,185 +0,0 @@ -# Importing TypeScript into Swift - -Learn how to leverage TypeScript definitions to create type-safe bindings for JavaScript APIs in your Swift code. - -## Overview - -> Important: This feature is still experimental. No API stability is guaranteed, and the API may change in future releases. - -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). - -BridgeJS enables seamless integration between Swift and JavaScript by automatically generating Swift bindings from TypeScript declaration files (`.d.ts`). This provides type-safe access to JavaScript APIs directly from your Swift code. - -The key benefits of this approach over `@dynamicMemberLookup`-based APIs include: - -- **Type Safety**: Catch errors at compile-time rather than runtime -- **IDE Support**: Get autocompletion and documentation in your Swift editor -- **Performance**: Eliminating dynamism allows us to optimize the glue code - -If you prefer keeping your project simple, you can continue using `@dynamicMemberLookup`-based APIs. - -## Getting Started - -### Step 1: Configure Your Package - -First, add the BridgeJS plugin to your Swift package by modifying your `Package.swift` file: - -```swift -// swift-tools-version:6.0 - -import PackageDescription - -let package = Package( - name: "MyApp", - dependencies: [ - .package(url: "https://github.com/swiftwasm/JavaScriptKit.git", branch: "main") - ], - targets: [ - .executableTarget( - name: "MyApp", - dependencies: ["JavaScriptKit"], - swiftSettings: [ - // This is required because the generated code depends on @_extern(wasm) - .enableExperimentalFeature("Extern") - ], - plugins: [ - // Add build plugin for processing @JS and generate Swift glue code - .plugin(name: "BridgeJS", package: "JavaScriptKit") - ] - ) - ] -) -``` - -### Step 2: Create TypeScript Definitions - -Create a file named `bridge-js.d.ts` in your target source directory (e.g. `Sources//bridge-js.d.ts`). This file defines the JavaScript APIs you want to use in Swift: - -```typescript -// Simple function -export function consoleLog(message: string): void; - -// Define a subset of DOM API you want to use -interface Document { - // Properties - title: string; - readonly body: HTMLElement; - - // Methods - getElementById(id: string): HTMLElement; - createElement(tagName: string): HTMLElement; -} - -// You can use type-level operations like `Pick` to reuse -// type definitions provided by `lib.dom.d.ts`. -interface HTMLElement extends Pick { - appendChild(child: HTMLElement): void; - // TODO: Function types on function signatures are not supported yet. - // addEventListener(event: string, handler: (event: any) => void): void; -} - -// Provide access to `document` -export function getDocument(): Document; -``` - -BridgeJS will generate Swift code that matches these TypeScript declarations. For example: - -```swift -func consoleLog(message: String) - -struct Document { - var title: String { get set } - var body: HTMLElement { get } - - func getElementById(_ id: String) -> HTMLElement - func createElement(_ tagName: String) -> HTMLElement -} - -struct HTMLElement { - var innerText: String { get set } - var className: String { get set } - - func appendChild(_ child: HTMLElement) -} - -func getDocument() -> Document -``` - -### Step 3: Build Your Package - -Build your package with the following command: - -```bash -swift package --swift-sdk $SWIFT_SDK_ID js -``` - -This command: -1. Processes your TypeScript definition files -2. Generates corresponding Swift bindings -3. Compiles your Swift code to WebAssembly -4. Produces JavaScript glue code in `.build/plugins/PackageToJS/outputs/` - -> Note: For larger projects, you may want to generate the BridgeJS code ahead of time to improve build performance. See for more information. - -### Step 4: Use the Generated Swift Bindings - -The BridgeJS plugin automatically generates Swift bindings that match your TypeScript definitions. You can now use these APIs directly in your Swift code: - -```swift -import JavaScriptKit - -@JS func run() { - // Simple function call - consoleLog("Hello from Swift!") - - // Get `document` - let document = getDocument() - - // Property access - document.title = "My Swift App" - - // Method calls - let button = document.createElement("button") - button.innerText = "Click Me" - - // TODO: Function types on function signatures are not supported yet. - // buttion.addEventListener("click") { _ in - // print("On click!") - // } - - // DOM manipulation - let container = document.getElementById("app") - container.appendChild(button) -} -``` - -### Step 5: Inject JavaScript Implementations - -The final step is to provide the actual JavaScript implementations for the TypeScript declarations you defined. You need to create a JavaScript file that initializes your WebAssembly module with the appropriate implementations: - -```javascript -// index.js -import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; - -// Initialize the WebAssembly module with JavaScript implementations -const { exports } = await init({ - getImports() { - return { - consoleLog: (message) => { - console.log(message); - }, - getDocument: () => document, - } - } -}); - -// Call the entry point of your Swift application -exports.run(); -``` - -## Topics - -- -- -- -- diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript/Importing-TS-Class.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript/Importing-TS-Class.md deleted file mode 100644 index e04bb9e75..000000000 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript/Importing-TS-Class.md +++ /dev/null @@ -1,64 +0,0 @@ -# Importing TypeScript Classes into Swift - -Learn how TypeScript classes map to Swift when importing APIs. - -## Overview - -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). - -BridgeJS reads class declarations in your `bridge-js.d.ts` and generates Swift structs that represent JS objects. Constructors, methods, and properties are bridged via thunks that call into your JavaScript implementations at runtime. - -## Example - -TypeScript definition (`bridge-js.d.ts`): - -```typescript -export class Greeter { - readonly id: string; - message: string; - constructor(id: string, name: string); - greet(): string; -} -``` - -Generated Swift API: - -```swift -struct Greeter { - init(id: String, name: String) throws(JSException) - - // Properties - // Readonly property - var id: String { get throws(JSException) } - // Writable property - var message: String { get throws(JSException) } - func setMessage(_ newValue: String) throws(JSException) - - // Methods - func greet() throws(JSException) -> String -} -``` - -Notes: -- Property setters are emitted as `set(_:)` functions, not Swift `set` accessors since `set` accessors can't have `throws` -- All thunks throw `JSException` if the underlying JS throws. - -JavaScript implementation wiring (provided by your app): - -```javascript -// index.js -import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; - -class Greeter { - readonly id: string; - message: string; - constructor(id: string, name: string) { ... } - greet(): string { ... } -} - -const { exports } = await init({ - getImports() { - return { Greeter }; - } -}); -``` diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript/Importing-TS-Function.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript/Importing-TS-Function.md deleted file mode 100644 index 060ac390f..000000000 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript/Importing-TS-Function.md +++ /dev/null @@ -1,60 +0,0 @@ -# Importing TypeScript Functions into Swift - -Learn how functions declared in TypeScript become callable Swift functions. - -## Overview - -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). - -BridgeJS reads your `bridge-js.d.ts` and generates Swift thunks that call into JavaScript implementations provided at runtime. Each imported function becomes a top-level Swift function with the same name and a throwing signature. - -### Example - -TypeScript definition (`bridge-js.d.ts`): - -```typescript -export function add(a: number, b: number): number; -export function setTitle(title: string): void; -export function fetchUser(id: string): Promise; -``` - -Generated Swift signatures: - -```swift -func add(a: Double, b: Double) throws(JSException) -> Double -func setTitle(title: String) throws(JSException) -func fetchUser(id: String) throws(JSException) -> JSPromise -``` - -JavaScript implementation wiring (provided by your app): - -```javascript -// index.js -import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; - -const { exports } = await init({ - getImports() { - return { - add: (a, b) => a + b, - setTitle: (title) => { document.title = title }, - fetchUser: (id) => fetch(`/api/users/${id}`).then(r => r.json()), - }; - } -}); -``` - -### Error handling - -- All imported Swift functions are generated as `throws(JSException)` and will throw if the underlying JS implementation throws. - -## Supported features - -| Feature | Status | -|:--|:--| -| Primitive parameter/result types: (e.g. `boolean`, `number`) | ✅ | -| `string` parameter/result type | ✅ | -| Enums in signatures | ❌ | -| Async function | ✅ | -| Generics | ❌ | - - diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript/Importing-TS-Interface.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript/Importing-TS-Interface.md deleted file mode 100644 index 0e0aed0de..000000000 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript/Importing-TS-Interface.md +++ /dev/null @@ -1,34 +0,0 @@ -# Importing TypeScript Interfaces into Swift - -Learn how TypeScript interfaces become Swift value types with methods and properties. - -## Overview - -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). - -BridgeJS converts TS interfaces to Swift structs conforming to an internal bridging protocol and provides thunks for methods and properties that call into your JavaScript implementations. - -> Note: Interfaces are bridged very similarly to classes. Methods and properties map the same way. See for more details. - -### Example - -TypeScript definition (`bridge-js.d.ts`): - -```typescript -export interface HTMLElement { - readonly innerText: string; - className: string; - appendChild(child: HTMLElement): void; -} -``` - -Generated Swift API: - -```swift -struct HTMLElement { - var innerText: String { get throws(JSException) } - var className: String { get throws(JSException) } - func setClassName(_ newValue: String) throws(JSException) - func appendChild(_ child: HTMLElement) throws(JSException) -} -``` diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript/Importing-TS-TypeAlias.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript/Importing-TS-TypeAlias.md deleted file mode 100644 index b5242ee33..000000000 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript/Importing-TS-TypeAlias.md +++ /dev/null @@ -1,47 +0,0 @@ -# Importing TypeScript Type Aliases into Swift - -Understand how TypeScript type aliases are handled when generating Swift bindings. - -## Overview - -> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). - -BridgeJS resolves TypeScript aliases while importing. If an alias names an anonymous object type, Swift will generate a corresponding bridged struct using that name. - -> Note: When a type alias names an anonymous object type, its bridging behavior (constructors not applicable, but methods/properties if referenced) mirrors class/interface importing. See for more details. - -### Examples - -```typescript -// Primitive alias → maps to the underlying primitive -export type Price = number; - -// Object-shaped alias with a name → becomes a named bridged type when referenced -export type User = { - readonly id: string; - name: string; - age: Price; -} - -export function getUser(): User; -``` - -Generated Swift (simplified): - -```swift -// Price → Double - -struct User { - // Readonly property - var id: String { get throws(JSException) } - - // Writable properties - var name: String { get throws(JSException) } - func setName(_ newValue: String) throws(JSException) - - var age: Double { get throws(JSException) } - func setAge(_ newValue: Double) throws(JSException) -} - -func getUser() throws(JSException) -> User -``` diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Introducing-BridgeJS.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Introducing-BridgeJS.md new file mode 100644 index 000000000..da4ae0a06 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Introducing-BridgeJS.md @@ -0,0 +1,32 @@ +# Introducing BridgeJS + +Faster, easier Swift–JavaScript bridging for WebAssembly. + +## Overview + +**BridgeJS** is a layer underneath JavaScriptKit that makes Swift–JavaScript interop **faster and easier**: you declare the shape of the API in Swift (or in TypeScript, which generates Swift), and the tool generates glue code. + +Benefits over the dynamic `JSObject` / `JSValue` APIs include: + +- **Performance** - Generated code is specialized per interface, so crossing the bridge typically costs less than using generic dynamic APIs. +- **Type safety** - Mistakes are caught at compile time instead of at runtime. +- **Easier integration** - Declarative annotations and optional TypeScript input replace manual boilerplate (closures, serializers, cached strings). + +You can still use the dynamic APIs when you need them; BridgeJS is an additional option for boundaries where you want strong typing and better performance. + +## Two directions + +BridgeJS supports both directions of the bridge: + +1. **Export Swift to JavaScript** - Expose Swift functions, classes, and types to JavaScript using the ``JS(namespace:enumStyle:)`` macro. JavaScript can then call into your Swift code. See . +2. **Import JavaScript into Swift** - Make JavaScript APIs (functions, classes, globals like `document` or `console`) callable from Swift with macros such as ``JSClass(jsName:from:)``. Start with . You can also generate the same bindings from a TypeScript file; see . + +Many apps use both: import DOM or host APIs into Swift, and export an entry point or callbacks to JavaScript. + +## Getting started + +- To **call Swift from JavaScript**: +- To **call JavaScript from Swift**: +- To **generate bindings from TypeScript**: + +All require the same package and build setup; see for configuration. diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Setting-up-BridgeJS.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Setting-up-BridgeJS.md new file mode 100644 index 000000000..99a3d5b1c --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Setting-up-BridgeJS.md @@ -0,0 +1,60 @@ +# Setting up BridgeJS + +Package and build setup required for all BridgeJS workflows + +## Overview + +BridgeJS requires the JavaScriptKit package dependency, the experimental `Extern` Swift feature, and the BridgeJS build plugin. The same configuration applies whether you are exporting Swift to JavaScript, importing JavaScript into Swift with macros, and generating bindings from a TypeScript file. + +## Package.swift + +Add the JavaScriptKit dependency, enable the Extern feature on the target that uses BridgeJS, and register the BridgeJS plugin: + +```swift +// swift-tools-version:6.0 + +import PackageDescription + +let package = Package( + name: "MyApp", + dependencies: [ + .package(url: "https://github.com/swiftwasm/JavaScriptKit.git", branch: "main") + ], + targets: [ + .executableTarget( + name: "MyApp", + dependencies: ["JavaScriptKit"], + swiftSettings: [ + .enableExperimentalFeature("Extern") + ], + plugins: [ + .plugin(name: "BridgeJS", package: "JavaScriptKit") + ] + ) + ] +) +``` + +- **Dependency**: The target must depend on `"JavaScriptKit"`. +- **Extern feature**: Required because the generated bridge code uses `@_extern(wasm)`. +- **BridgeJS plugin**: Processes macro annotations to generate glue code and, [when present, `bridge-js.d.ts`; generates JS binding Swift code](). + +## Build command + +Build the package for the JavaScript/WebAssembly SDK: + +```bash +swift package --swift-sdk $SWIFT_SDK_ID js +``` + +This command: + +1. Runs the BridgeJS plugin +2. Compiles Swift to WebAssembly and generates JavaScript glue and TypeScript type definitions. +3. Writes output to `.build/plugins/PackageToJS/outputs/Package/`. + +For package layout and how to consume the output from JavaScript, see . + +## Larger projects + +The build plugin runs on every build. For larger projects, generating bridge code ahead of time can improve build performance. See . diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md index c872c0dda..81a135af3 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md @@ -1,18 +1,22 @@ -# TypeScript and Swift Type Mapping +# Supported Types -Use this page as a quick reference for how common TypeScript types appear in Swift when importing, and how exported Swift types surface on the TypeScript side. +Swift types and their JavaScript/TypeScript equivalents at the BridgeJS boundary. -## Type mapping +## Swift and JavaScript type mapping -| TypeScript type | Swift type | -|:--|:--| -| `number` | `Double` | -| `string` | `String` | -| `boolean` | `Bool` | -| `T[]` | `[T]` | -| TODO | `Dictionary` | -| `T \| undefined` | TODO | -| `T \| null` | `Optional` | -| `Promise` | `JSPromise` | -| `any` / `unknown` / `object` | `JSObject` | -| Other types | `JSObject` | +| Swift type | JavaScript | TypeScript | +|:--|:--|:--| +| `Int`, `UInt`, `Double`, `Float` | number | `number` | +| `String` | string | `string` | +| `Bool` | boolean | `boolean` | +| `Void` | - | `void` | +| `[T]` | array | `T[]` | +| `[String: T]` | object | `Record` | +| `Optional` | `null` or `T` | `T \| null` | +| ``JSUndefinedOr`` `` | `undefined` or `T` | `T \| undefined` | +| ``JSObject`` | object | `object` | +| ``JSValue`` | any | `any` | + +## See Also + +- diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/FAQ.md b/Sources/JavaScriptKit/Documentation.docc/Articles/FAQ.md new file mode 100644 index 000000000..aabd2f008 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/FAQ.md @@ -0,0 +1,28 @@ +# FAQ + +Common questions about JavaScriptKit and BridgeJS. + +## Why does the initialization need to be async? Why must I await it? + +Initialization is asynchronous because the runtime must **fetch and instantiate the WebAssembly module** before your Swift code can run. That means: + +1. **Fetching** the `.wasm` binary (e.g. over the network or from disk). +2. **Instantiating** it with `WebAssembly.instantiate()` (or `instantiateStreaming()`), which compiles the module and allocates the linear memory and table. + +Until that completes, there is no WebAssembly instance to call into, so the entry point that sets up the Swift–JavaScript bridge has to be `async` and must be `await`ed from the JavaScript host (e.g. in your `index.js` or HTML script). This matches the standard WebAssembly JavaScript API, which is promise-based. + +## Why does every imported JavaScript interface via BridgeJS declare `throws(JSException)`? + +This is a conservative, safety-oriented design. Calling into JavaScript can throw at any time. If the Swift call site does not expect errors (i.e. the call is not in a `throws` context and the compiler does not force handling), then when JavaScript throws: + +- Control leaves the WebAssembly call frames **without running function epilogues**. +- Even a `do { } catch { }` in Swift does not run its `catch` block in the way you might expect, because unwinding crosses the WASM/JS boundary. +- **`defer` blocks are not executed** in those frames. + +That can lead to **inconsistent memory state** and **resource leaks**. To avoid that, every call that might invoke JavaScript is modeled as throwing: all imported JS functions, property accessors, and related operations are marked with `throws(JSException)`. That way: + +- The compiler requires you to handle or propagate errors. +- You explicitly decide how to react to JavaScript exceptions (e.g. `try`/`catch`, or propagating `throws`). +- Epilogues and cleanup run in a well-defined way when you handle the error in Swift. + +So the “everything throws” rule is there to keep behavior predictable and safe when crossing the Swift–JavaScript boundary. diff --git a/Sources/JavaScriptKit/Documentation.docc/Documentation.md b/Sources/JavaScriptKit/Documentation.docc/Documentation.md index 51ee62539..75fd24d44 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Documentation.md +++ b/Sources/JavaScriptKit/Documentation.docc/Documentation.md @@ -59,14 +59,25 @@ Check out the [examples](https://github.com/swiftwasm/JavaScriptKit/tree/main/Ex - - - +- ### BridgeJS -- +- +- - +- +- +- - - - +- +- ``JS(namespace:enumStyle:)`` +- ``JSFunction(jsName:from:)`` +- ``JSClass(jsName:from:)`` +- ``JSGetter(jsName:from:)`` +- ``JSSetter(jsName:from:)`` ### Core APIs diff --git a/Sources/JavaScriptKit/Macros.swift b/Sources/JavaScriptKit/Macros.swift index 8decf1a76..67b3488bf 100644 --- a/Sources/JavaScriptKit/Macros.swift +++ b/Sources/JavaScriptKit/Macros.swift @@ -125,7 +125,7 @@ public macro JS(namespace: String? = nil, enumStyle: JSEnumStyle = .const) = Bui /// Example: /// /// ```swift -/// @_spi(Experimental) import JavaScriptKit +/// import JavaScriptKit /// /// @JSGetter var count: Int /// @@ -137,7 +137,6 @@ public macro JS(namespace: String? = nil, enumStyle: JSEnumStyle = .const) = Bui /// - Parameter from: Selects where the property is read from. /// Use `.global` to read from `globalThis` (e.g. `console`, `document`). @attached(accessor) -@_spi(Experimental) public macro JSGetter(jsName: String? = nil, from: JSImportFrom? = nil) = #externalMacro(module: "BridgeJSMacros", type: "JSGetterMacro") @@ -151,12 +150,11 @@ public macro JSGetter(jsName: String? = nil, from: JSImportFrom? = nil) = /// Example: /// /// ```swift -/// @_spi(Experimental) import JavaScriptKit +/// import JavaScriptKit /// /// @JSSetter func setName(_ value: String) throws (JSException) /// ``` @attached(body) -@_spi(Experimental) public macro JSSetter(jsName: String? = nil, from: JSImportFrom? = nil) = #externalMacro(module: "BridgeJSMacros", type: "JSSetterMacro") @@ -167,7 +165,7 @@ public macro JSSetter(jsName: String? = nil, from: JSImportFrom? = nil) = /// Example: /// /// ```swift -/// @_spi(Experimental) import JavaScriptKit +/// import JavaScriptKit /// /// @JSFunction func greet() throws (JSException) -> String /// @JSFunction init(_ name: String) throws (JSException) @@ -178,7 +176,6 @@ public macro JSSetter(jsName: String? = nil, from: JSImportFrom? = nil) = /// - Parameter from: Selects where the function is looked up from. /// Use `.global` to call a function on `globalThis` (e.g. `setTimeout`). @attached(body) -@_spi(Experimental) public macro JSFunction(jsName: String? = nil, from: JSImportFrom? = nil) = #externalMacro(module: "BridgeJSMacros", type: "JSFunctionMacro") @@ -189,7 +186,7 @@ public macro JSFunction(jsName: String? = nil, from: JSImportFrom? = nil) = /// Example: /// /// ```swift -/// @_spi(Experimental) import JavaScriptKit +/// import JavaScriptKit /// /// @JSClass /// struct JsGreeter { @@ -204,6 +201,5 @@ public macro JSFunction(jsName: String? = nil, from: JSImportFrom? = nil) = /// Use `.global` to construct globals like `WebSocket` via `globalThis`. @attached(member, names: named(jsObject), named(init(unsafelyWrapping:))) @attached(extension, conformances: _JSBridgedClass) -@_spi(Experimental) public macro JSClass(jsName: String? = nil, from: JSImportFrom? = nil) = #externalMacro(module: "BridgeJSMacros", type: "JSClassMacro") diff --git a/Tests/BridgeJSRuntimeTests/ClosureSupportTests.swift b/Tests/BridgeJSRuntimeTests/ClosureSupportTests.swift index 320fec526..8078ed777 100644 --- a/Tests/BridgeJSRuntimeTests/ClosureSupportTests.swift +++ b/Tests/BridgeJSRuntimeTests/ClosureSupportTests.swift @@ -1,5 +1,5 @@ import XCTest -@_spi(Experimental) import JavaScriptKit +import JavaScriptKit @JSClass struct ClosureSupportImports { diff --git a/Tests/BridgeJSRuntimeTests/DictionaryTests.swift b/Tests/BridgeJSRuntimeTests/DictionaryTests.swift index ba702205d..95f2706e6 100644 --- a/Tests/BridgeJSRuntimeTests/DictionaryTests.swift +++ b/Tests/BridgeJSRuntimeTests/DictionaryTests.swift @@ -1,4 +1,4 @@ -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit import XCTest final class DictionaryTests: XCTestCase { diff --git a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift index 7f9a20586..97c2d5fbf 100644 --- a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift +++ b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift @@ -1,5 +1,5 @@ import XCTest -@_spi(Experimental) import JavaScriptKit +import JavaScriptKit import JavaScriptEventLoop @_extern(wasm, module: "BridgeJSRuntimeTests", name: "runJsWorks") diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.Macros.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.Macros.swift index 9f500f4a4..c63a421e0 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.Macros.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.Macros.swift @@ -4,7 +4,7 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func jsRoundTripVoid() throws(JSException) -> Void diff --git a/Tests/BridgeJSRuntimeTests/ImportArrayAPIs.swift b/Tests/BridgeJSRuntimeTests/ImportArrayAPIs.swift index 3f33de86a..104304d5b 100644 --- a/Tests/BridgeJSRuntimeTests/ImportArrayAPIs.swift +++ b/Tests/BridgeJSRuntimeTests/ImportArrayAPIs.swift @@ -1,4 +1,4 @@ -@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit +@_spi(BridgeJS) import JavaScriptKit @JSFunction func jsRoundTripIntArray(_ items: [Int]) throws(JSException) -> [Int] @JSFunction func jsArrayLength(_ items: [Int]) throws(JSException) -> Int diff --git a/Tests/BridgeJSRuntimeTests/ImportStructAPIs.swift b/Tests/BridgeJSRuntimeTests/ImportStructAPIs.swift index 82908701c..41929772e 100644 --- a/Tests/BridgeJSRuntimeTests/ImportStructAPIs.swift +++ b/Tests/BridgeJSRuntimeTests/ImportStructAPIs.swift @@ -1,4 +1,4 @@ -@_spi(Experimental) import JavaScriptKit +import JavaScriptKit @JS struct Point { diff --git a/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift b/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift index 454f5011d..998f8b90f 100644 --- a/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift +++ b/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift @@ -1,5 +1,5 @@ import XCTest -@_spi(Experimental) import JavaScriptKit +import JavaScriptKit import JavaScriptEventLoop @JSFunction func runJsOptionalSupportTests() throws diff --git a/Tests/BridgeJSRuntimeTests/StructAPIs.swift b/Tests/BridgeJSRuntimeTests/StructAPIs.swift index 38e7b12e6..6c0079dd1 100644 --- a/Tests/BridgeJSRuntimeTests/StructAPIs.swift +++ b/Tests/BridgeJSRuntimeTests/StructAPIs.swift @@ -1,4 +1,4 @@ -@_spi(Experimental) import JavaScriptKit +import JavaScriptKit @JS struct PointerFields { var raw: UnsafeRawPointer diff --git a/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift b/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift index 1a3dd0a4f..7eefbad56 100644 --- a/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift +++ b/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift @@ -1,5 +1,5 @@ import XCTest -@_spi(Experimental) import JavaScriptKit +import JavaScriptKit @JSClass struct SwiftClassSupportImports { @JSFunction static func jsRoundTripGreeter(_ greeter: Greeter) throws(JSException) -> Greeter From a931787ea6fd3fb9c92a97ad4bb51a3ddc743a42 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 13 Feb 2026 14:47:01 +0900 Subject: [PATCH 40/40] Documentation tweaks --- Plugins/BridgeJS/README.md | 6 ++-- README.md | 6 ++-- .../Articles/BridgeJS/Introducing-BridgeJS.md | 4 +-- .../Articles/BridgeJS/Unsupported-Features.md | 28 +++++++++++++++++++ .../Documentation.docc/Articles/FAQ.md | 4 +-- .../Documentation.docc/Documentation.md | 1 + 6 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Unsupported-Features.md diff --git a/Plugins/BridgeJS/README.md b/Plugins/BridgeJS/README.md index 0b6ad121e..9e1e0aa08 100644 --- a/Plugins/BridgeJS/README.md +++ b/Plugins/BridgeJS/README.md @@ -10,8 +10,8 @@ BridgeJS provides easy interoperability between Swift and JavaScript/TypeScript. It enables: -1. **Export Swift to JavaScript** – Expose Swift functions, classes, and types to JavaScript; the plugin generates TypeScript definitions (`.d.ts`) for the exported API. -2. **Import JavaScript into Swift** – Make JavaScript/TypeScript APIs callable from Swift with macro-annotated bindings or bindings generated from a TypeScript declaration file (`bridge-js.d.ts`). +1. **Export Swift to JavaScript** - Expose Swift functions, classes, and types to JavaScript; the plugin generates TypeScript definitions (`.d.ts`) for the exported API. +2. **Import JavaScript into Swift** - Make JavaScript/TypeScript APIs callable from Swift with macro-annotated bindings or bindings generated from a TypeScript declaration file (`bridge-js.d.ts`). The workflow is: @@ -174,7 +174,7 @@ For detailed semantics, see the [How It Works sections](https://swiftpackageinde `BridgeJSToolInternal` exposes pipeline stages for debugging: - `emit-skeleton` - Parse Swift files (or `-` for stdin) and print the BridgeJS skeleton as JSON. -- `emit-swift-thunks` — Read skeleton JSON (from a file or `-` for stdin) and print the generated Swift glue (export and import thunks). +- `emit-swift-thunks` - Read skeleton JSON (from a file or `-` for stdin) and print the generated Swift glue (export and import thunks). - `emit-js` / `emit-dts` - Read skeleton JSON files (or `-` for stdin) and print the .js/.d.ts Use these to inspect parser output and generated code without running the full generate/link pipeline. diff --git a/README.md b/README.md index b5cb04801..ffb029298 100644 --- a/README.md +++ b/README.md @@ -48,14 +48,14 @@ _ = document.body.appendChild(button) BridgeJS provides easy interoperability between Swift and JavaScript/TypeScript. It enables: -- **Export Swift to JavaScript** – Expose Swift functions, classes, and types to JavaScript; the plugin also generates TypeScript definitions (`.d.ts`) for the exported API. -- **Import JavaScript into Swift** – Make JavaScript/TypeScript APIs (functions, classes, globals like `document` or `console`) callable from Swift with type-safe bindings. You can declare bindings with macros in Swift or generate them from a TypeScript declaration file (`bridge-js.d.ts`). +- **Export Swift to JavaScript** - Expose Swift functions, classes, and types to JavaScript; the plugin also generates TypeScript definitions (`.d.ts`) for the exported API. +- **Import JavaScript into Swift** - Make JavaScript/TypeScript APIs (functions, classes, globals like `document` or `console`) callable from Swift with type-safe bindings. You can declare bindings with macros in Swift or generate them from a TypeScript declaration file (`bridge-js.d.ts`). For architecture details, see the [BridgeJS Plugin README](Plugins/BridgeJS/README.md). For package and build setup, see [Setting up BridgeJS](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/setting-up-bridgejs) in the documentation. ### Exporting Swift to JavaScript -Mark Swift code with `@JS` (the ``JS(namespace:enumStyle:)`` attribute) to make it callable from JavaScript: +Mark Swift code with `@JS` to make it callable from JavaScript: ```swift import JavaScriptKit diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Introducing-BridgeJS.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Introducing-BridgeJS.md index da4ae0a06..43f778f0c 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Introducing-BridgeJS.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Introducing-BridgeJS.md @@ -1,10 +1,10 @@ # Introducing BridgeJS -Faster, easier Swift–JavaScript bridging for WebAssembly. +Faster, easier Swift-JavaScript bridging for WebAssembly. ## Overview -**BridgeJS** is a layer underneath JavaScriptKit that makes Swift–JavaScript interop **faster and easier**: you declare the shape of the API in Swift (or in TypeScript, which generates Swift), and the tool generates glue code. +**BridgeJS** is a layer underneath JavaScriptKit that makes Swift-JavaScript interop **faster and easier**: you declare the shape of the API in Swift (or in TypeScript, which generates Swift), and the tool generates glue code. Benefits over the dynamic `JSObject` / `JSValue` APIs include: diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Unsupported-Features.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Unsupported-Features.md new file mode 100644 index 000000000..7ba25f7ae --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Unsupported-Features.md @@ -0,0 +1,28 @@ +# Unsupported Features in BridgeJS + +Limitations and unsupported patterns when using BridgeJS. + +## Overview + +BridgeJS generates glue code per Swift target (module). Some patterns that are valid in Swift or TypeScript are not supported across the bridge today. This article summarizes the main limitations so you can design your APIs accordingly. + +## Type usage crossing module boundary + +BridgeJS does **not** support using a type across module boundaries in the following situations. + +### Exporting Swift: types from another Swift module + +If you have multiple Swift targets (e.g. a library and an app), you **cannot** use a type defined in one target in an exported API of another target. + +**Unsupported example:** Module `App` exports a function that takes or returns a type defined in module `Lib`: + +```swift +// In module Lib +@JS public struct LibPoint { + let x: Double + let y: Double +} + +// In module App (depends on Lib) - unsupported +@JS public func transform(_ p: LibPoint) -> LibPoint { ... } +``` diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/FAQ.md b/Sources/JavaScriptKit/Documentation.docc/Articles/FAQ.md index aabd2f008..c4f22a437 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/FAQ.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/FAQ.md @@ -9,7 +9,7 @@ Initialization is asynchronous because the runtime must **fetch and instantiate 1. **Fetching** the `.wasm` binary (e.g. over the network or from disk). 2. **Instantiating** it with `WebAssembly.instantiate()` (or `instantiateStreaming()`), which compiles the module and allocates the linear memory and table. -Until that completes, there is no WebAssembly instance to call into, so the entry point that sets up the Swift–JavaScript bridge has to be `async` and must be `await`ed from the JavaScript host (e.g. in your `index.js` or HTML script). This matches the standard WebAssembly JavaScript API, which is promise-based. +Until that completes, there is no WebAssembly instance to call into, so the entry point that sets up the Swift-JavaScript bridge has to be `async` and must be `await`ed from the JavaScript host (e.g. in your `index.js` or HTML script). This matches the standard WebAssembly JavaScript API, which is promise-based. ## Why does every imported JavaScript interface via BridgeJS declare `throws(JSException)`? @@ -25,4 +25,4 @@ That can lead to **inconsistent memory state** and **resource leaks**. To avoid - You explicitly decide how to react to JavaScript exceptions (e.g. `try`/`catch`, or propagating `throws`). - Epilogues and cleanup run in a well-defined way when you handle the error in Swift. -So the “everything throws” rule is there to keep behavior predictable and safe when crossing the Swift–JavaScript boundary. +So the “everything throws” rule is there to keep behavior predictable and safe when crossing the Swift-JavaScript boundary. diff --git a/Sources/JavaScriptKit/Documentation.docc/Documentation.md b/Sources/JavaScriptKit/Documentation.docc/Documentation.md index 75fd24d44..097203f50 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Documentation.md +++ b/Sources/JavaScriptKit/Documentation.docc/Documentation.md @@ -72,6 +72,7 @@ Check out the [examples](https://github.com/swiftwasm/JavaScriptKit/tree/main/Ex - - - +- - - ``JS(namespace:enumStyle:)`` - ``JSFunction(jsName:from:)``