diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4f1eb0a5b..6b5ace046 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,6 +14,8 @@ jobs: download-url: https://download.swift.org/swift-6.1-release/ubuntu2204/swift-6.1-RELEASE/swift-6.1-RELEASE-ubuntu22.04.tar.gz wasi-backend: Node target: "wasm32-unknown-wasi" + env: | + JAVASCRIPTKIT_DISABLE_TRACING_TRAIT=1 - os: ubuntu-24.04 toolchain: download-url: https://download.swift.org/development/ubuntu2404/swift-DEVELOPMENT-SNAPSHOT-2025-12-01-a/swift-DEVELOPMENT-SNAPSHOT-2025-12-01-a-ubuntu24.04.tar.gz @@ -36,6 +38,12 @@ jobs: steps: - name: Checkout uses: actions/checkout@v6 + - name: Export matrix env + if: ${{ matrix.entry.env != '' && matrix.entry.env != null }} + run: | + cat <<'EOF' >> "$GITHUB_ENV" + ${{ matrix.entry.env }} + EOF - uses: ./.github/actions/install-swift with: download-url: ${{ matrix.entry.toolchain.download-url }} @@ -59,6 +67,33 @@ jobs: - run: swift test --package-path ./Plugins/PackageToJS - run: swift test --package-path ./Plugins/BridgeJS + test-bridgejs-against-swift-versions: + name: Test BridgeJS against Swift versions + strategy: + matrix: + entry: + - image: "swift:6.1.2" + swift-syntax-version: "601.0.0" + - image: "swift:6.2" + swift-syntax-version: "602.0.0" + runs-on: ubuntu-latest + container: + image: ${{ matrix.entry.image }} + steps: + - uses: actions/checkout@v6 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + - name: Install TypeScript + run: npm install --prefix Plugins/BridgeJS/Sources/TS2Swift/JavaScript + - name: Run BridgeJS tests + # NOTE: Seems like the prebuilt SwiftSyntax binaries are not compatible with + # non-macro dependents, so disable experimental prebuilts for now. + run: swift test --disable-experimental-prebuilts --package-path ./Plugins/BridgeJS + env: + BRIDGEJS_OVERRIDE_SWIFT_SYNTAX_VERSION: ${{ matrix.entry.swift-syntax-version }} + native-build: # Check native build to make it easy to develop applications by Xcode name: Build for native target diff --git a/Benchmarks/Sources/Benchmarks.swift b/Benchmarks/Sources/Benchmarks.swift index 661aba63e..59da8c96c 100644 --- a/Benchmarks/Sources/Benchmarks.swift +++ b/Benchmarks/Sources/Benchmarks.swift @@ -111,6 +111,22 @@ enum ComplexResult { } } +@JS class OptionalReturnRoundtrip { + @JS init() {} + + @JS func makeIntSome() -> Int? { 42 } + @JS func makeIntNone() -> Int? { nil } + + @JS func makeBoolSome() -> Bool? { true } + @JS func makeBoolNone() -> Bool? { nil } + + @JS func makeDoubleSome() -> Double? { 0.5 } + @JS func makeDoubleNone() -> Double? { nil } + + @JS func makeStringSome() -> String? { "Hello, world" } + @JS func makeStringNone() -> String? { nil } +} + // MARK: - Struct Performance Tests @JS struct SimpleStruct { @@ -241,6 +257,134 @@ enum ComplexResult { } } +// MARK: - Array Performance Tests + +@JS struct Point { + var x: Double + var y: Double +} + +@JS class ArrayRoundtrip { + @JS init() {} + + // MARK: Primitive Arrays - Int + + @JS func takeIntArray(_ values: [Int]) {} + @JS func makeIntArray() -> [Int] { + return Array(1...1000) + } + @JS func roundtripIntArray(_ values: [Int]) -> [Int] { + return values + } + + @JS func makeIntArrayLarge() -> [Int] { + return Array(1...10000) + } + + // MARK: Primitive Arrays - Double + + @JS func takeDoubleArray(_ values: [Double]) {} + @JS func makeDoubleArray() -> [Double] { + return (1...1000).map { Double($0) * 1.1 } + } + @JS func roundtripDoubleArray(_ values: [Double]) -> [Double] { + return values + } + + // MARK: Primitive Arrays - String + + @JS func takeStringArray(_ values: [String]) {} + @JS func makeStringArray() -> [String] { + return ["one", "two", "three", "four", "five"] + } + @JS func roundtripStringArray(_ values: [String]) -> [String] { + return values + } + + // MARK: Struct Arrays + + @JS func takePointArray(_ points: [Point]) {} + @JS func makePointArray() -> [Point] { + return [ + Point(x: 0.0, y: 0.0), + Point(x: 1.0, y: 1.0), + Point(x: 2.0, y: 2.0), + Point(x: 3.0, y: 3.0), + Point(x: 4.0, y: 4.0), + ] + } + @JS func roundtripPointArray(_ points: [Point]) -> [Point] { + return points + } + + @JS func makePointArrayLarge() -> [Point] { + return (0..<50).map { Point(x: Double($0), y: Double($0)) } + } + + // MARK: Nested Arrays + + @JS func takeNestedIntArray(_ values: [[Int]]) {} + @JS func makeNestedIntArray() -> [[Int]] { + return [ + [1, 2, 3], + [4, 5, 6], + [7, 8, 9], + ] + } + @JS func roundtripNestedIntArray(_ values: [[Int]]) -> [[Int]] { + return values + } + + @JS func takeNestedPointArray(_ points: [[Point]]) {} + @JS func makeNestedPointArray() -> [[Point]] { + return [ + [Point(x: 0.0, y: 0.0), Point(x: 1.0, y: 1.0)], + [Point(x: 2.0, y: 2.0), Point(x: 3.0, y: 3.0)], + [Point(x: 4.0, y: 4.0), Point(x: 5.0, y: 5.0)], + ] + } + @JS func roundtripNestedPointArray(_ points: [[Point]]) -> [[Point]] { + return points + } + + // MARK: Optional Element Arrays + + @JS func takeOptionalIntArray(_ values: [Int?]) {} + @JS func makeOptionalIntArray() -> [Int?] { + return [1, nil, 3, nil, 5, nil, 7, nil, 9, nil] + } + @JS func roundtripOptionalIntArray(_ values: [Int?]) -> [Int?] { + return values + } + + @JS func takeOptionalPointArray(_ points: [Point?]) {} + @JS func makeOptionalPointArray() -> [Point?] { + return [ + Point(x: 0.0, y: 0.0), + nil, + Point(x: 2.0, y: 2.0), + nil, + Point(x: 4.0, y: 4.0), + ] + } + @JS func roundtripOptionalPointArray(_ points: [Point?]) -> [Point?] { + return points + } + + // MARK: Optional Arrays + + @JS func takeOptionalArray(_ values: [Int]?) {} + @JS func makeOptionalArraySome() -> [Int]? { + return [1, 2, 3, 4, 5] + } + @JS func makeOptionalArrayNone() -> [Int]? { + return nil + } + @JS func roundtripOptionalArray(_ values: [Int]?) -> [Int]? { + return values + } +} + @JS func run() { let call = Benchmark("Call") diff --git a/Benchmarks/Sources/Generated/BridgeJS.swift b/Benchmarks/Sources/Generated/BridgeJS.swift index 85d81f4a2..86f4c87dc 100644 --- a/Benchmarks/Sources/Generated/BridgeJS.swift +++ b/Benchmarks/Sources/Generated/BridgeJS.swift @@ -11,15 +11,15 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> APIResult { switch caseId { case 0: - return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .success(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 1: - return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) case 2: - return .flag(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .flag(Bool.bridgeJSLiftParameter(_swift_js_pop_i32())) case 3: - return .rate(Float.bridgeJSLiftParameter(_swift_js_pop_param_f32())) + return .rate(Float.bridgeJSLiftParameter(_swift_js_pop_f32())) case 4: - return .precise(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64())) + return .precise(Double.bridgeJSLiftParameter(_swift_js_pop_f64())) case 5: return .info default: @@ -38,10 +38,10 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } return Int32(0) case .failure(let param0): - _swift_js_push_int(Int32(param0)) + _swift_js_push_i32(Int32(param0)) return Int32(1) case .flag(let param0): - _swift_js_push_int(param0 ? 1 : 0) + _swift_js_push_i32(param0 ? 1 : 0) return Int32(2) case .rate(let param0): _swift_js_push_f32(param0) @@ -74,10 +74,10 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } case .failure(let param0): _swift_js_push_tag(Int32(1)) - _swift_js_push_int(Int32(param0)) + _swift_js_push_i32(Int32(param0)) case .flag(let param0): _swift_js_push_tag(Int32(2)) - _swift_js_push_int(param0 ? 1 : 0) + _swift_js_push_i32(param0 ? 1 : 0) case .rate(let param0): _swift_js_push_tag(Int32(3)) _swift_js_push_f32(param0) @@ -94,17 +94,17 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> ComplexResult { switch caseId { case 0: - return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .success(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 1: - return .error(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .error(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32())) case 2: - return .location(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .location(Double.bridgeJSLiftParameter(_swift_js_pop_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_f64()), String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 3: - return .status(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .status(Bool.bridgeJSLiftParameter(_swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32()), String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 4: - return .coordinates(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64())) + return .coordinates(Double.bridgeJSLiftParameter(_swift_js_pop_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_f64())) case 5: - return .comprehensive(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .comprehensive(Bool.bridgeJSLiftParameter(_swift_js_pop_i32()), Bool.bridgeJSLiftParameter(_swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32()), Double.bridgeJSLiftParameter(_swift_js_pop_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_f64()), String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 6: return .info default: @@ -127,7 +127,7 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { __bjs_param0.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(Int32(param1)) return Int32(1) case .location(let param0, let param1, let param2): _swift_js_push_f64(param0) @@ -138,8 +138,8 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { } return Int32(2) case .status(let param0, let param1, let param2): - _swift_js_push_int(param0 ? 1 : 0) - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(param0 ? 1 : 0) + _swift_js_push_i32(Int32(param1)) var __bjs_param2 = param2 __bjs_param2.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) @@ -151,10 +151,10 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_f64(param2) return Int32(4) case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): - _swift_js_push_int(param0 ? 1 : 0) - _swift_js_push_int(param1 ? 1 : 0) - _swift_js_push_int(Int32(param2)) - _swift_js_push_int(Int32(param3)) + _swift_js_push_i32(param0 ? 1 : 0) + _swift_js_push_i32(param1 ? 1 : 0) + _swift_js_push_i32(Int32(param2)) + _swift_js_push_i32(Int32(param3)) _swift_js_push_f64(param4) _swift_js_push_f64(param5) var __bjs_param6 = param6 @@ -199,7 +199,7 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { __bjs_param0.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(Int32(param1)) case .location(let param0, let param1, let param2): _swift_js_push_tag(Int32(2)) _swift_js_push_f64(param0) @@ -210,8 +210,8 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { } case .status(let param0, let param1, let param2): _swift_js_push_tag(Int32(3)) - _swift_js_push_int(param0 ? 1 : 0) - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(param0 ? 1 : 0) + _swift_js_push_i32(Int32(param1)) var __bjs_param2 = param2 __bjs_param2.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) @@ -223,10 +223,10 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_f64(param2) case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): _swift_js_push_tag(Int32(5)) - _swift_js_push_int(param0 ? 1 : 0) - _swift_js_push_int(param1 ? 1 : 0) - _swift_js_push_int(Int32(param2)) - _swift_js_push_int(Int32(param3)) + _swift_js_push_i32(param0 ? 1 : 0) + _swift_js_push_i32(param1 ? 1 : 0) + _swift_js_push_i32(Int32(param2)) + _swift_js_push_i32(Int32(param3)) _swift_js_push_f64(param4) _swift_js_push_f64(param5) var __bjs_param6 = param6 @@ -249,11 +249,11 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { extension SimpleStruct: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> SimpleStruct { - let precise = Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()) - let rate = Float.bridgeJSLiftParameter(_swift_js_pop_param_f32()) - let flag = Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()) - let count = Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()) - let name = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) + let precise = Double.bridgeJSLiftParameter(_swift_js_pop_f64()) + let rate = Float.bridgeJSLiftParameter(_swift_js_pop_f32()) + let flag = Bool.bridgeJSLiftParameter(_swift_js_pop_i32()) + let count = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) + let name = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) return SimpleStruct(name: name, count: count, flag: flag, rate: rate, precise: precise) } @@ -262,18 +262,50 @@ extension SimpleStruct: _BridgedSwiftStruct { __bjs_name.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(self.count)) - _swift_js_push_int(self.flag ? 1 : 0) + _swift_js_push_i32(Int32(self.count)) + _swift_js_push_i32(self.flag ? 1 : 0) _swift_js_push_f32(self.rate) _swift_js_push_f64(self.precise) } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_SimpleStruct(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_SimpleStruct())) + } } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_SimpleStruct") +fileprivate func _bjs_struct_lower_SimpleStruct(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_SimpleStruct(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_SimpleStruct") +fileprivate func _bjs_struct_lift_SimpleStruct() -> Int32 +#else +fileprivate func _bjs_struct_lift_SimpleStruct() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + extension Address: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> Address { - let zipCode = Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()) - let city = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let street = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) + let zipCode = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) + let city = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let street = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) return Address(street: street, city: city, zipCode: zipCode) } @@ -286,16 +318,48 @@ extension Address: _BridgedSwiftStruct { __bjs_city.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(self.zipCode)) + _swift_js_push_i32(Int32(self.zipCode)) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Address(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Address())) } } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Address") +fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Address") +fileprivate func _bjs_struct_lift_Address() -> Int32 +#else +fileprivate func _bjs_struct_lift_Address() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + extension Person: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> Person { - let email = Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32(), _swift_js_pop_param_int32()) + let email = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32(), _swift_js_pop_i32()) let address = Address.bridgeJSLiftParameter() - let age = Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()) - let name = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) + let age = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) + let name = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) return Person(name: name, age: age, address: address, email: email) } @@ -304,7 +368,7 @@ extension Person: _BridgedSwiftStruct { __bjs_name.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(self.age)) + _swift_js_push_i32(Int32(self.age)) self.address.bridgeJSLowerReturn() let __bjs_isSome_email = self.email != nil if let __bjs_unwrapped_email = self.email { @@ -313,28 +377,60 @@ extension Person: _BridgedSwiftStruct { _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } } - _swift_js_push_int(__bjs_isSome_email ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_email ? 1 : 0) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Person(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Person())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Person") +fileprivate func _bjs_struct_lower_Person(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_Person(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Person") +fileprivate func _bjs_struct_lift_Person() -> Int32 +#else +fileprivate func _bjs_struct_lift_Person() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif extension ComplexStruct: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> ComplexStruct { - let metadata = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let tags = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let score = Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()) - let active = Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()) - let title = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let id = Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()) + let metadata = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let tags = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let score = Double.bridgeJSLiftParameter(_swift_js_pop_f64()) + let active = Bool.bridgeJSLiftParameter(_swift_js_pop_i32()) + let title = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let id = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) return ComplexStruct(id: id, title: title, active: active, score: score, tags: tags, metadata: metadata) } @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - _swift_js_push_int(Int32(self.id)) + _swift_js_push_i32(Int32(self.id)) var __bjs_title = self.title __bjs_title.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(self.active ? 1 : 0) + _swift_js_push_i32(self.active ? 1 : 0) _swift_js_push_f64(self.score) var __bjs_tags = self.tags __bjs_tags.withUTF8 { ptr in @@ -345,7 +441,84 @@ extension ComplexStruct: _BridgedSwiftStruct { _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_ComplexStruct(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_ComplexStruct())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_ComplexStruct") +fileprivate func _bjs_struct_lower_ComplexStruct(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_ComplexStruct(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_ComplexStruct") +fileprivate func _bjs_struct_lift_ComplexStruct() -> Int32 +#else +fileprivate func _bjs_struct_lift_ComplexStruct() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +extension Point: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> Point { + let y = Double.bridgeJSLiftParameter(_swift_js_pop_f64()) + let x = Double.bridgeJSLiftParameter(_swift_js_pop_f64()) + return Point(x: x, y: y) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { + _swift_js_push_f64(self.x) + _swift_js_push_f64(self.y) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Point())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Point") +fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Point") +fileprivate func _bjs_struct_lift_Point() -> Int32 +#else +fileprivate func _bjs_struct_lift_Point() -> Int32 { + fatalError("Only available on WebAssembly") } +#endif @_expose(wasm, "bjs_run") @_cdecl("bjs_run") @@ -671,6 +844,130 @@ fileprivate func _bjs_StringRoundtrip_wrap(_ pointer: UnsafeMutableRawPointer) - } #endif +@_expose(wasm, "bjs_OptionalReturnRoundtrip_init") +@_cdecl("bjs_OptionalReturnRoundtrip_init") +public func _bjs_OptionalReturnRoundtrip_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = OptionalReturnRoundtrip() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalReturnRoundtrip_makeIntSome") +@_cdecl("bjs_OptionalReturnRoundtrip_makeIntSome") +public func _bjs_OptionalReturnRoundtrip_makeIntSome(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalReturnRoundtrip.bridgeJSLiftParameter(_self).makeIntSome() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalReturnRoundtrip_makeIntNone") +@_cdecl("bjs_OptionalReturnRoundtrip_makeIntNone") +public func _bjs_OptionalReturnRoundtrip_makeIntNone(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalReturnRoundtrip.bridgeJSLiftParameter(_self).makeIntNone() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalReturnRoundtrip_makeBoolSome") +@_cdecl("bjs_OptionalReturnRoundtrip_makeBoolSome") +public func _bjs_OptionalReturnRoundtrip_makeBoolSome(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalReturnRoundtrip.bridgeJSLiftParameter(_self).makeBoolSome() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalReturnRoundtrip_makeBoolNone") +@_cdecl("bjs_OptionalReturnRoundtrip_makeBoolNone") +public func _bjs_OptionalReturnRoundtrip_makeBoolNone(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalReturnRoundtrip.bridgeJSLiftParameter(_self).makeBoolNone() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalReturnRoundtrip_makeDoubleSome") +@_cdecl("bjs_OptionalReturnRoundtrip_makeDoubleSome") +public func _bjs_OptionalReturnRoundtrip_makeDoubleSome(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalReturnRoundtrip.bridgeJSLiftParameter(_self).makeDoubleSome() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalReturnRoundtrip_makeDoubleNone") +@_cdecl("bjs_OptionalReturnRoundtrip_makeDoubleNone") +public func _bjs_OptionalReturnRoundtrip_makeDoubleNone(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalReturnRoundtrip.bridgeJSLiftParameter(_self).makeDoubleNone() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalReturnRoundtrip_makeStringSome") +@_cdecl("bjs_OptionalReturnRoundtrip_makeStringSome") +public func _bjs_OptionalReturnRoundtrip_makeStringSome(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalReturnRoundtrip.bridgeJSLiftParameter(_self).makeStringSome() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalReturnRoundtrip_makeStringNone") +@_cdecl("bjs_OptionalReturnRoundtrip_makeStringNone") +public func _bjs_OptionalReturnRoundtrip_makeStringNone(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalReturnRoundtrip.bridgeJSLiftParameter(_self).makeStringNone() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalReturnRoundtrip_deinit") +@_cdecl("bjs_OptionalReturnRoundtrip_deinit") +public func _bjs_OptionalReturnRoundtrip_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension OptionalReturnRoundtrip: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_OptionalReturnRoundtrip_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "Benchmarks", name: "bjs_OptionalReturnRoundtrip_wrap") +fileprivate func _bjs_OptionalReturnRoundtrip_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_OptionalReturnRoundtrip_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + @_expose(wasm, "bjs_StructRoundtrip_init") @_cdecl("bjs_StructRoundtrip_init") public func _bjs_StructRoundtrip_init() -> UnsafeMutableRawPointer { @@ -1175,6 +1472,650 @@ fileprivate func _bjs_ClassRoundtrip_wrap(_ pointer: UnsafeMutableRawPointer) -> } #endif +@_expose(wasm, "bjs_ArrayRoundtrip_init") +@_cdecl("bjs_ArrayRoundtrip_init") +public func _bjs_ArrayRoundtrip_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = ArrayRoundtrip() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_takeIntArray") +@_cdecl("bjs_ArrayRoundtrip_takeIntArray") +public func _bjs_ArrayRoundtrip_takeIntArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + ArrayRoundtrip.bridgeJSLiftParameter(_self).takeIntArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_makeIntArray") +@_cdecl("bjs_ArrayRoundtrip_makeIntArray") +public func _bjs_ArrayRoundtrip_makeIntArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeIntArray() + for __bjs_elem_ret in ret { + _swift_js_push_i32(Int32(__bjs_elem_ret))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_roundtripIntArray") +@_cdecl("bjs_ArrayRoundtrip_roundtripIntArray") +public func _bjs_ArrayRoundtrip_roundtripIntArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).roundtripIntArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_i32(Int32(__bjs_elem_ret))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_makeIntArrayLarge") +@_cdecl("bjs_ArrayRoundtrip_makeIntArrayLarge") +public func _bjs_ArrayRoundtrip_makeIntArrayLarge(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeIntArrayLarge() + for __bjs_elem_ret in ret { + _swift_js_push_i32(Int32(__bjs_elem_ret))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_takeDoubleArray") +@_cdecl("bjs_ArrayRoundtrip_takeDoubleArray") +public func _bjs_ArrayRoundtrip_takeDoubleArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + ArrayRoundtrip.bridgeJSLiftParameter(_self).takeDoubleArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Double] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Double.bridgeJSLiftParameter(_swift_js_pop_f64())) + } + __result.reverse() + return __result + }()) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_makeDoubleArray") +@_cdecl("bjs_ArrayRoundtrip_makeDoubleArray") +public func _bjs_ArrayRoundtrip_makeDoubleArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeDoubleArray() + for __bjs_elem_ret in ret { + _swift_js_push_f64(__bjs_elem_ret)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_roundtripDoubleArray") +@_cdecl("bjs_ArrayRoundtrip_roundtripDoubleArray") +public func _bjs_ArrayRoundtrip_roundtripDoubleArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).roundtripDoubleArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Double] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Double.bridgeJSLiftParameter(_swift_js_pop_f64())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_f64(__bjs_elem_ret)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_takeStringArray") +@_cdecl("bjs_ArrayRoundtrip_takeStringArray") +public func _bjs_ArrayRoundtrip_takeStringArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + ArrayRoundtrip.bridgeJSLiftParameter(_self).takeStringArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [String] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_makeStringArray") +@_cdecl("bjs_ArrayRoundtrip_makeStringArray") +public func _bjs_ArrayRoundtrip_makeStringArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeStringArray() + for __bjs_elem_ret in ret { + var __bjs_ret_elem = __bjs_elem_ret + __bjs_ret_elem.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + }} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_roundtripStringArray") +@_cdecl("bjs_ArrayRoundtrip_roundtripStringArray") +public func _bjs_ArrayRoundtrip_roundtripStringArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).roundtripStringArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [String] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + var __bjs_ret_elem = __bjs_elem_ret + __bjs_ret_elem.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + }} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_takePointArray") +@_cdecl("bjs_ArrayRoundtrip_takePointArray") +public func _bjs_ArrayRoundtrip_takePointArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + ArrayRoundtrip.bridgeJSLiftParameter(_self).takePointArray(_: { + 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 + }()) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_makePointArray") +@_cdecl("bjs_ArrayRoundtrip_makePointArray") +public func _bjs_ArrayRoundtrip_makePointArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makePointArray() + for __bjs_elem_ret in ret { + __bjs_elem_ret.bridgeJSLowerReturn()} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_roundtripPointArray") +@_cdecl("bjs_ArrayRoundtrip_roundtripPointArray") +public func _bjs_ArrayRoundtrip_roundtripPointArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).roundtripPointArray(_: { + 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)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_makePointArrayLarge") +@_cdecl("bjs_ArrayRoundtrip_makePointArrayLarge") +public func _bjs_ArrayRoundtrip_makePointArrayLarge(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makePointArrayLarge() + for __bjs_elem_ret in ret { + __bjs_elem_ret.bridgeJSLowerReturn()} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_takeNestedIntArray") +@_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({ + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + } + __result.reverse() + return __result + }()) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_makeNestedIntArray") +@_cdecl("bjs_ArrayRoundtrip_makeNestedIntArray") +public func _bjs_ArrayRoundtrip_makeNestedIntArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeNestedIntArray() + for __bjs_elem_ret in ret { + for __bjs_elem_ret_elem in __bjs_elem_ret { + _swift_js_push_i32(Int32(__bjs_elem_ret_elem))} + _swift_js_push_i32(Int32(__bjs_elem_ret.count))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_roundtripNestedIntArray") +@_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({ + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + for __bjs_elem_ret_elem in __bjs_elem_ret { + _swift_js_push_i32(Int32(__bjs_elem_ret_elem))} + _swift_js_push_i32(Int32(__bjs_elem_ret.count))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_takeNestedPointArray") +@_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({ + 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 + }()) + } + __result.reverse() + return __result + }()) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_makeNestedPointArray") +@_cdecl("bjs_ArrayRoundtrip_makeNestedPointArray") +public func _bjs_ArrayRoundtrip_makeNestedPointArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeNestedPointArray() + for __bjs_elem_ret in ret { + for __bjs_elem_ret_elem in __bjs_elem_ret { + __bjs_elem_ret_elem.bridgeJSLowerReturn()} + _swift_js_push_i32(Int32(__bjs_elem_ret.count))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_roundtripNestedPointArray") +@_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({ + 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 + }()) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + for __bjs_elem_ret_elem in __bjs_elem_ret { + __bjs_elem_ret_elem.bridgeJSLowerReturn()} + _swift_js_push_i32(Int32(__bjs_elem_ret.count))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_takeOptionalIntArray") +@_cdecl("bjs_ArrayRoundtrip_takeOptionalIntArray") +public func _bjs_ArrayRoundtrip_takeOptionalIntArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + ArrayRoundtrip.bridgeJSLiftParameter(_self).takeOptionalIntArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_makeOptionalIntArray") +@_cdecl("bjs_ArrayRoundtrip_makeOptionalIntArray") +public func _bjs_ArrayRoundtrip_makeOptionalIntArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeOptionalIntArray() + for __bjs_elem_ret in ret { + let __bjs_isSome_ret_elem = __bjs_elem_ret != nil + if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { + _swift_js_push_i32(Int32(__bjs_unwrapped_ret_elem))} + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_roundtripOptionalIntArray") +@_cdecl("bjs_ArrayRoundtrip_roundtripOptionalIntArray") +public func _bjs_ArrayRoundtrip_roundtripOptionalIntArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).roundtripOptionalIntArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __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 { + _swift_js_push_i32(Int32(__bjs_unwrapped_ret_elem))} + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_takeOptionalPointArray") +@_cdecl("bjs_ArrayRoundtrip_takeOptionalPointArray") +public func _bjs_ArrayRoundtrip_takeOptionalPointArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + ArrayRoundtrip.bridgeJSLiftParameter(_self).takeOptionalPointArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Optional.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_makeOptionalPointArray") +@_cdecl("bjs_ArrayRoundtrip_makeOptionalPointArray") +public func _bjs_ArrayRoundtrip_makeOptionalPointArray(_ _self: UnsafeMutableRawPointer) -> Void { + #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)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_roundtripOptionalPointArray") +@_cdecl("bjs_ArrayRoundtrip_roundtripOptionalPointArray") +public func _bjs_ArrayRoundtrip_roundtripOptionalPointArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).roundtripOptionalPointArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Optional.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __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)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_takeOptionalArray") +@_cdecl("bjs_ArrayRoundtrip_takeOptionalArray") +public func _bjs_ArrayRoundtrip_takeOptionalArray(_ _self: UnsafeMutableRawPointer, _ values: Int32) -> Void { + #if arch(wasm32) + ArrayRoundtrip.bridgeJSLiftParameter(_self).takeOptionalArray(_: { + if values == 0 { + return Optional<[Int]>.none + } else { + return { + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }() + } + }()) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_makeOptionalArraySome") +@_cdecl("bjs_ArrayRoundtrip_makeOptionalArraySome") +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 { + for __bjs_elem_ret in __bjs_unwrapped_ret { + _swift_js_push_i32(Int32(__bjs_elem_ret))} + _swift_js_push_i32(Int32(__bjs_unwrapped_ret.count))} + _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_makeOptionalArrayNone") +@_cdecl("bjs_ArrayRoundtrip_makeOptionalArrayNone") +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 { + for __bjs_elem_ret in __bjs_unwrapped_ret { + _swift_js_push_i32(Int32(__bjs_elem_ret))} + _swift_js_push_i32(Int32(__bjs_unwrapped_ret.count))} + _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_roundtripOptionalArray") +@_cdecl("bjs_ArrayRoundtrip_roundtripOptionalArray") +public func _bjs_ArrayRoundtrip_roundtripOptionalArray(_ _self: UnsafeMutableRawPointer, _ values: Int32) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).roundtripOptionalArray(_: { + if values == 0 { + return Optional<[Int]>.none + } else { + return { + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }() + } + }()) + let __bjs_isSome_ret = ret != nil + if let __bjs_unwrapped_ret = ret { + for __bjs_elem_ret in __bjs_unwrapped_ret { + _swift_js_push_i32(Int32(__bjs_elem_ret))} + _swift_js_push_i32(Int32(__bjs_unwrapped_ret.count))} + _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_deinit") +@_cdecl("bjs_ArrayRoundtrip_deinit") +public func _bjs_ArrayRoundtrip_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension ArrayRoundtrip: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_ArrayRoundtrip_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "Benchmarks", name: "bjs_ArrayRoundtrip_wrap") +fileprivate func _bjs_ArrayRoundtrip_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_ArrayRoundtrip_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + #if arch(wasm32) @_extern(wasm, module: "Benchmarks", name: "bjs_benchmarkHelperNoop") fileprivate func bjs_benchmarkHelperNoop() -> Void diff --git a/Benchmarks/Sources/Generated/JavaScript/BridgeJS.json b/Benchmarks/Sources/Generated/JavaScript/BridgeJS.json index 27a245f56..cb081ab39 100644 --- a/Benchmarks/Sources/Generated/JavaScript/BridgeJS.json +++ b/Benchmarks/Sources/Generated/JavaScript/BridgeJS.json @@ -424,6 +424,194 @@ ], "swiftCallName" : "StringRoundtrip" }, + { + "constructor" : { + "abiName" : "bjs_OptionalReturnRoundtrip_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_OptionalReturnRoundtrip_makeIntSome", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeIntSome", + "parameters" : [ + + ], + "returnType" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "abiName" : "bjs_OptionalReturnRoundtrip_makeIntNone", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeIntNone", + "parameters" : [ + + ], + "returnType" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "abiName" : "bjs_OptionalReturnRoundtrip_makeBoolSome", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeBoolSome", + "parameters" : [ + + ], + "returnType" : { + "optional" : { + "_0" : { + "bool" : { + + } + } + } + } + }, + { + "abiName" : "bjs_OptionalReturnRoundtrip_makeBoolNone", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeBoolNone", + "parameters" : [ + + ], + "returnType" : { + "optional" : { + "_0" : { + "bool" : { + + } + } + } + } + }, + { + "abiName" : "bjs_OptionalReturnRoundtrip_makeDoubleSome", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeDoubleSome", + "parameters" : [ + + ], + "returnType" : { + "optional" : { + "_0" : { + "double" : { + + } + } + } + } + }, + { + "abiName" : "bjs_OptionalReturnRoundtrip_makeDoubleNone", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeDoubleNone", + "parameters" : [ + + ], + "returnType" : { + "optional" : { + "_0" : { + "double" : { + + } + } + } + } + }, + { + "abiName" : "bjs_OptionalReturnRoundtrip_makeStringSome", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeStringSome", + "parameters" : [ + + ], + "returnType" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "abiName" : "bjs_OptionalReturnRoundtrip_makeStringNone", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeStringNone", + "parameters" : [ + + ], + "returnType" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "name" : "OptionalReturnRoundtrip", + "properties" : [ + + ], + "swiftCallName" : "OptionalReturnRoundtrip" + }, { "constructor" : { "abiName" : "bjs_StructRoundtrip_init", @@ -1055,70 +1243,984 @@ ], "swiftCallName" : "ClassRoundtrip" - } - ], - "enums" : [ + }, { - "cases" : [ + "constructor" : { + "abiName" : "bjs_ArrayRoundtrip_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ { - "associatedValues" : [ + "abiName" : "bjs_ArrayRoundtrip_takeIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeIntArray", + "parameters" : [ { + "label" : "_", + "name" : "values", "type" : { - "string" : { + "array" : { + "_0" : { + "int" : { + } + } } } } ], - "name" : "success" + "returnType" : { + "void" : { + + } + } }, { - "associatedValues" : [ - { - "type" : { + "abiName" : "bjs_ArrayRoundtrip_makeIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeIntArray", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { "int" : { } } } - ], - "name" : "failure" + } }, { - "associatedValues" : [ + "abiName" : "bjs_ArrayRoundtrip_roundtripIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripIntArray", + "parameters" : [ { + "label" : "_", + "name" : "values", "type" : { - "bool" : { + "array" : { + "_0" : { + "int" : { + } + } } } } ], - "name" : "flag" - }, - { - "associatedValues" : [ - { - "type" : { - "float" : { + "returnType" : { + "array" : { + "_0" : { + "int" : { } } } - ], - "name" : "rate" + } }, { - "associatedValues" : [ - { - "type" : { - "double" : { + "abiName" : "bjs_ArrayRoundtrip_makeIntArrayLarge", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeIntArrayLarge", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "int" : { } } } - ], - "name" : "precise" + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_takeDoubleArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeDoubleArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_makeDoubleArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeDoubleArray", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_roundtripDoubleArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripDoubleArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_takeStringArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeStringArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_makeStringArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeStringArray", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_roundtripStringArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripStringArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_takePointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takePointArray", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_makePointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makePointArray", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_roundtripPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripPointArray", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_makePointArrayLarge", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makePointArrayLarge", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_takeNestedIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeNestedIntArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_makeNestedIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeNestedIntArray", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_roundtripNestedIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripNestedIntArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_takeNestedPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeNestedPointArray", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_makeNestedPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeNestedPointArray", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_roundtripNestedPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripNestedPointArray", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_takeOptionalIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeOptionalIntArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_makeOptionalIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeOptionalIntArray", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_roundtripOptionalIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalIntArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_takeOptionalPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeOptionalPointArray", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_makeOptionalPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeOptionalPointArray", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_roundtripOptionalPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalPointArray", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_takeOptionalArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeOptionalArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "optional" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_makeOptionalArraySome", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeOptionalArraySome", + "parameters" : [ + + ], + "returnType" : { + "optional" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_makeOptionalArrayNone", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeOptionalArrayNone", + "parameters" : [ + + ], + "returnType" : { + "optional" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_roundtripOptionalArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "optional" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + } + ], + "name" : "ArrayRoundtrip", + "properties" : [ + + ], + "swiftCallName" : "ArrayRoundtrip" + } + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + } + ], + "name" : "flag" + }, + { + "associatedValues" : [ + { + "type" : { + "float" : { + + } + } + } + ], + "name" : "rate" + }, + { + "associatedValues" : [ + { + "type" : { + "double" : { + + } + } + } + ], + "name" : "precise" }, { "associatedValues" : [ @@ -1579,6 +2681,35 @@ } ], "swiftCallName" : "ComplexStruct" + }, + { + "methods" : [ + + ], + "name" : "Point", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "x", + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "y", + "type" : { + "double" : { + + } + } + } + ], + "swiftCallName" : "Point" } ] }, diff --git a/Benchmarks/run.js b/Benchmarks/run.js index 5c27e6fff..5a1ae61e6 100644 --- a/Benchmarks/run.js +++ b/Benchmarks/run.js @@ -17,9 +17,17 @@ function updateProgress(current, total, label = '', width) { const completed = Math.round(width * (percent / 100)); const remaining = width - completed; const bar = '█'.repeat(completed) + '░'.repeat(remaining); - process.stdout.clearLine(); - process.stdout.cursorTo(0); - process.stdout.write(`${label} [${bar}] ${current}/${total}`); + const canUpdateLine = + process.stdout.isTTY && + typeof process.stdout.clearLine === "function" && + typeof process.stdout.cursorTo === "function"; + if (canUpdateLine) { + process.stdout.clearLine(); + process.stdout.cursorTo(0); + process.stdout.write(`${label} [${bar}] ${current}/${total}`); + } else if (current === 0 || current === total) { + console.log(`${label} [${bar}] ${current}/${total}`); + } } /** @@ -263,14 +271,21 @@ function saveJsonResults(filePath, data) { /** * Run a single benchmark iteration * @param {Object} results - Results object to store benchmark data + * @param {(name: string) => boolean} nameFilter - Name filter + * @param {number} iterations - Loop iterations per JS benchmark * @returns {Promise} */ -async function singleRun(results, nameFilter) { +async function singleRun(results, nameFilter, iterations) { const options = await defaultNodeSetup({}) const benchmarkRunner = (name, body) => { if (nameFilter && !nameFilter(name)) { return; } + // Warmup to reduce JIT/IC noise. + body(); + if (typeof globalThis.gc === "function") { + globalThis.gc(); + } const startTime = performance.now(); body(); const endTime = performance.now(); @@ -291,7 +306,6 @@ async function singleRun(results, nameFilter) { exports.run(); const enumRoundtrip = new exports.EnumRoundtrip(); - const iterations = 100_000; benchmarkRunner("EnumRoundtrip/takeEnum success", () => { for (let i = 0; i < iterations; i++) { enumRoundtrip.take({ tag: APIResult.Tag.Success, param0: "Hello, world" }) @@ -455,6 +469,48 @@ async function singleRun(results, nameFilter) { } }) + const optionalReturnRoundtrip = new exports.OptionalReturnRoundtrip(); + benchmarkRunner("OptionalReturnRoundtrip/makeIntSome", () => { + for (let i = 0; i < iterations; i++) { + optionalReturnRoundtrip.makeIntSome() + } + }) + benchmarkRunner("OptionalReturnRoundtrip/makeIntNone", () => { + for (let i = 0; i < iterations; i++) { + optionalReturnRoundtrip.makeIntNone() + } + }) + benchmarkRunner("OptionalReturnRoundtrip/makeBoolSome", () => { + for (let i = 0; i < iterations; i++) { + optionalReturnRoundtrip.makeBoolSome() + } + }) + benchmarkRunner("OptionalReturnRoundtrip/makeBoolNone", () => { + for (let i = 0; i < iterations; i++) { + optionalReturnRoundtrip.makeBoolNone() + } + }) + benchmarkRunner("OptionalReturnRoundtrip/makeDoubleSome", () => { + for (let i = 0; i < iterations; i++) { + optionalReturnRoundtrip.makeDoubleSome() + } + }) + benchmarkRunner("OptionalReturnRoundtrip/makeDoubleNone", () => { + for (let i = 0; i < iterations; i++) { + optionalReturnRoundtrip.makeDoubleNone() + } + }) + benchmarkRunner("OptionalReturnRoundtrip/makeStringSome", () => { + for (let i = 0; i < iterations; i++) { + optionalReturnRoundtrip.makeStringSome() + } + }) + benchmarkRunner("OptionalReturnRoundtrip/makeStringNone", () => { + for (let i = 0; i < iterations; i++) { + optionalReturnRoundtrip.makeStringNone() + } + }) + // Struct performance tests const structRoundtrip = new exports.StructRoundtrip(); @@ -584,15 +640,245 @@ async function singleRun(results, nameFilter) { classRoundtrip.roundtripAddressClass(address) } }) + + // Array performance tests + const arrayRoundtrip = new exports.ArrayRoundtrip(); + + // Primitive Arrays - Int + benchmarkRunner("ArrayRoundtrip/takeIntArray", () => { + const arr = Array.from({length: 1000}, (_, i) => i + 1) + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.takeIntArray(arr) + } + }) + benchmarkRunner("ArrayRoundtrip/makeIntArray", () => { + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.makeIntArray() + } + }) + benchmarkRunner("ArrayRoundtrip/roundtripIntArray", () => { + const arr = Array.from({length: 1000}, (_, i) => i + 1) + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.roundtripIntArray(arr) + } + }) + benchmarkRunner("ArrayRoundtrip/makeIntArrayLarge", () => { + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.makeIntArrayLarge() + } + }) + + // Primitive Arrays - Double + benchmarkRunner("ArrayRoundtrip/takeDoubleArray", () => { + const arr = Array.from({length: 1000}, (_, i) => (i + 1) * 1.1) + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.takeDoubleArray(arr) + } + }) + benchmarkRunner("ArrayRoundtrip/makeDoubleArray", () => { + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.makeDoubleArray() + } + }) + benchmarkRunner("ArrayRoundtrip/roundtripDoubleArray", () => { + const arr = Array.from({length: 1000}, (_, i) => (i + 1) * 1.1) + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.roundtripDoubleArray(arr) + } + }) + + // Primitive Arrays - String + benchmarkRunner("ArrayRoundtrip/takeStringArray", () => { + const arr = ["one", "two", "three", "four", "five"] + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.takeStringArray(arr) + } + }) + benchmarkRunner("ArrayRoundtrip/makeStringArray", () => { + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.makeStringArray() + } + }) + benchmarkRunner("ArrayRoundtrip/roundtripStringArray", () => { + const arr = ["one", "two", "three", "four", "five"] + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.roundtripStringArray(arr) + } + }) + + // Struct Arrays + benchmarkRunner("ArrayRoundtrip/takePointArray", () => { + const arr = [ + { x: 0.0, y: 0.0 }, + { x: 1.0, y: 1.0 }, + { x: 2.0, y: 2.0 }, + { x: 3.0, y: 3.0 }, + { x: 4.0, y: 4.0 } + ] + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.takePointArray(arr) + } + }) + benchmarkRunner("ArrayRoundtrip/makePointArray", () => { + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.makePointArray() + } + }) + benchmarkRunner("ArrayRoundtrip/roundtripPointArray", () => { + const arr = [ + { x: 0.0, y: 0.0 }, + { x: 1.0, y: 1.0 }, + { x: 2.0, y: 2.0 }, + { x: 3.0, y: 3.0 }, + { x: 4.0, y: 4.0 } + ] + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.roundtripPointArray(arr) + } + }) + benchmarkRunner("ArrayRoundtrip/makePointArrayLarge", () => { + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.makePointArrayLarge() + } + }) + + // Nested Arrays + benchmarkRunner("ArrayRoundtrip/takeNestedIntArray", () => { + const arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.takeNestedIntArray(arr) + } + }) + benchmarkRunner("ArrayRoundtrip/makeNestedIntArray", () => { + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.makeNestedIntArray() + } + }) + benchmarkRunner("ArrayRoundtrip/roundtripNestedIntArray", () => { + const arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.roundtripNestedIntArray(arr) + } + }) + + benchmarkRunner("ArrayRoundtrip/takeNestedPointArray", () => { + const arr = [ + [{ x: 0.0, y: 0.0 }, { x: 1.0, y: 1.0 }], + [{ x: 2.0, y: 2.0 }, { x: 3.0, y: 3.0 }], + [{ x: 4.0, y: 4.0 }, { x: 5.0, y: 5.0 }] + ] + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.takeNestedPointArray(arr) + } + }) + benchmarkRunner("ArrayRoundtrip/makeNestedPointArray", () => { + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.makeNestedPointArray() + } + }) + benchmarkRunner("ArrayRoundtrip/roundtripNestedPointArray", () => { + const arr = [ + [{ x: 0.0, y: 0.0 }, { x: 1.0, y: 1.0 }], + [{ x: 2.0, y: 2.0 }, { x: 3.0, y: 3.0 }], + [{ x: 4.0, y: 4.0 }, { x: 5.0, y: 5.0 }] + ] + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.roundtripNestedPointArray(arr) + } + }) + + // Optional Element Arrays + benchmarkRunner("ArrayRoundtrip/takeOptionalIntArray", () => { + const arr = [1, null, 3, null, 5, null, 7, null, 9, null] + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.takeOptionalIntArray(arr) + } + }) + benchmarkRunner("ArrayRoundtrip/makeOptionalIntArray", () => { + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.makeOptionalIntArray() + } + }) + benchmarkRunner("ArrayRoundtrip/roundtripOptionalIntArray", () => { + const arr = [1, null, 3, null, 5, null, 7, null, 9, null] + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.roundtripOptionalIntArray(arr) + } + }) + + benchmarkRunner("ArrayRoundtrip/takeOptionalPointArray", () => { + const arr = [ + { x: 0.0, y: 0.0 }, + null, + { x: 2.0, y: 2.0 }, + null, + { x: 4.0, y: 4.0 } + ] + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.takeOptionalPointArray(arr) + } + }) + benchmarkRunner("ArrayRoundtrip/makeOptionalPointArray", () => { + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.makeOptionalPointArray() + } + }) + benchmarkRunner("ArrayRoundtrip/roundtripOptionalPointArray", () => { + const arr = [ + { x: 0.0, y: 0.0 }, + null, + { x: 2.0, y: 2.0 }, + null, + { x: 4.0, y: 4.0 } + ] + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.roundtripOptionalPointArray(arr) + } + }) + + // Optional Arrays + benchmarkRunner("ArrayRoundtrip/takeOptionalArraySome", () => { + const arr = [1, 2, 3, 4, 5] + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.takeOptionalArray(arr) + } + }) + benchmarkRunner("ArrayRoundtrip/takeOptionalArrayNone", () => { + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.takeOptionalArray(null) + } + }) + benchmarkRunner("ArrayRoundtrip/makeOptionalArraySome", () => { + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.makeOptionalArraySome() + } + }) + benchmarkRunner("ArrayRoundtrip/makeOptionalArrayNone", () => { + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.makeOptionalArrayNone() + } + }) + benchmarkRunner("ArrayRoundtrip/roundtripOptionalArraySome", () => { + const arr = [1, 2, 3, 4, 5] + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.roundtripOptionalArray(arr) + } + }) + benchmarkRunner("ArrayRoundtrip/roundtripOptionalArrayNone", () => { + for (let i = 0; i < iterations; i++) { + arrayRoundtrip.roundtripOptionalArray(null) + } + }) } /** * Run until the coefficient of variation of measurements is below the threshold * @param {Object} results - Benchmark results object * @param {Object} options - Adaptive sampling options + * @param {number} iterations - Loop iterations per JS benchmark * @returns {Promise} */ -async function runUntilStable(results, options, width, nameFilter, filterArg) { +async function runUntilStable(results, options, width, nameFilter, filterArg, iterations) { const { minRuns = 5, maxRuns = 50, @@ -611,7 +897,7 @@ async function runUntilStable(results, options, width, nameFilter, filterArg) { // Update progress with estimated completion updateProgress(runs, maxRuns, "Benchmark Progress:", width); - await singleRun(results, nameFilter); + await singleRun(results, nameFilter, iterations); runs++; if (runs === 1 && Object.keys(results).length === 0) { @@ -674,6 +960,7 @@ Usage: node run.js [options] Options: --runs=NUMBER Number of benchmark runs (default: 10) + --iterations=NUMBER Loop iterations per JS benchmark (default: 100000) --output=FILENAME Save JSON results to specified file --baseline=FILENAME Compare results with baseline JSON file --adaptive Enable adaptive sampling (run until stable) @@ -689,6 +976,7 @@ async function main() { const args = parseArgs({ options: { runs: { type: 'string', default: '10' }, + iterations: { type: 'string', default: '100000' }, output: { type: 'string' }, baseline: { type: 'string' }, help: { type: 'boolean', default: false }, @@ -710,6 +998,12 @@ async function main() { const filterArg = args.values.filter; const nameFilter = createNameFilter(filterArg); + const iterations = parseInt(args.values.iterations, 10); + if (isNaN(iterations) || iterations <= 0) { + console.error('Invalid --iterations value:', args.values.iterations); + process.exit(1); + } + if (args.values.adaptive) { // Adaptive sampling mode const options = { @@ -723,7 +1017,7 @@ async function main() { console.log(`Results will be saved to: ${args.values.output}`); } - await runUntilStable(results, options, width, nameFilter, filterArg); + await runUntilStable(results, options, width, nameFilter, filterArg, iterations); } else { // Fixed number of runs mode const runs = parseInt(args.values.runs, 10); @@ -745,7 +1039,7 @@ async function main() { console.log("\nOverall Progress:"); for (let i = 0; i < runs; i++) { updateProgress(i, runs, "Benchmark Runs:", width); - await singleRun(results, nameFilter); + await singleRun(results, nameFilter, iterations); if (i === 0 && Object.keys(results).length === 0) { process.stdout.write("\n"); console.error(`No benchmarks matched filter: ${filterArg}`); diff --git a/Examples/ActorOnWebWorker/build.sh b/Examples/ActorOnWebWorker/build.sh index 62b31144c..4def77883 100755 --- a/Examples/ActorOnWebWorker/build.sh +++ b/Examples/ActorOnWebWorker/build.sh @@ -1,5 +1,5 @@ #!/bin/bash set -euxo pipefail -swift package --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1_threads:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1-threads}}" -c release \ +swift package --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1_threads:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1-threads}}" \ plugin --allow-writing-to-package-directory \ - js --use-cdn --output ./Bundle + js --use-cdn --output ./Bundle -c release diff --git a/Examples/Basic/build.sh b/Examples/Basic/build.sh index 7b5864c44..2351f4e2d 100755 --- a/Examples/Basic/build.sh +++ b/Examples/Basic/build.sh @@ -1,3 +1,3 @@ #!/bin/bash set -euxo pipefail -swift package --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1}}" -c "${1:-debug}" js --use-cdn +swift package --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1}}" js --use-cdn -c "${1:-debug}" diff --git a/Examples/Multithreading/build.sh b/Examples/Multithreading/build.sh index 62b31144c..4def77883 100755 --- a/Examples/Multithreading/build.sh +++ b/Examples/Multithreading/build.sh @@ -1,5 +1,5 @@ #!/bin/bash set -euxo pipefail -swift package --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1_threads:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1-threads}}" -c release \ +swift package --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1_threads:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1-threads}}" \ plugin --allow-writing-to-package-directory \ - js --use-cdn --output ./Bundle + js --use-cdn --output ./Bundle -c release diff --git a/Examples/OffscrenCanvas/build.sh b/Examples/OffscrenCanvas/build.sh index 62b31144c..4def77883 100755 --- a/Examples/OffscrenCanvas/build.sh +++ b/Examples/OffscrenCanvas/build.sh @@ -1,5 +1,5 @@ #!/bin/bash set -euxo pipefail -swift package --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1_threads:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1-threads}}" -c release \ +swift package --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1_threads:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1-threads}}" \ plugin --allow-writing-to-package-directory \ - js --use-cdn --output ./Bundle + js --use-cdn --output ./Bundle -c release diff --git a/Examples/PlayBridgeJS/build.sh b/Examples/PlayBridgeJS/build.sh index 97e4b0f95..d2589f798 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}}" -c "${1:-debug}" \ +env JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 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 + js --use-cdn --output ./Bundle -c "${1:-debug}" diff --git a/Makefile b/Makefile index 0c5d0122a..135465a73 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,9 @@ SWIFT_SDK_ID ?= +ifeq ($(JAVASCRIPTKIT_DISABLE_TRACING_TRAIT),1) + TRACING_ARGS := +else + TRACING_ARGS := --traits Tracing +endif .PHONY: bootstrap bootstrap: @@ -12,6 +17,7 @@ unittest: exit 2; \ } env JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --swift-sdk "$(SWIFT_SDK_ID)" \ + $(TRACING_ARGS) \ --disable-sandbox \ js test --prelude ./Tests/prelude.mjs -Xnode --expose-gc diff --git a/Package.swift b/Package.swift index a513ec406..1d4c8fb06 100644 --- a/Package.swift +++ b/Package.swift @@ -181,6 +181,7 @@ let package = Package( exclude: [ "bridge-js.config.json", "bridge-js.d.ts", + "bridge-js.global.d.ts", "Generated/JavaScript", ], swiftSettings: [ diff --git a/Package@swift-6.2.swift b/Package@swift-6.2.swift new file mode 100644 index 000000000..456a87ca0 --- /dev/null +++ b/Package@swift-6.2.swift @@ -0,0 +1,217 @@ +// swift-tools-version:6.2 + +import CompilerPluginSupport +import PackageDescription + +// NOTE: needed for embedded customizations, ideally this will not be necessary at all in the future, or can be replaced with traits +let shouldBuildForEmbedded = Context.environment["JAVASCRIPTKIT_EXPERIMENTAL_EMBEDDED_WASM"].flatMap(Bool.init) ?? false +let useLegacyResourceBundling = + Context.environment["JAVASCRIPTKIT_USE_LEGACY_RESOURCE_BUNDLING"].flatMap(Bool.init) ?? false +let enableTracingByEnv = Context.environment["JAVASCRIPTKIT_ENABLE_TRACING"].flatMap(Bool.init) ?? false + +let tracingTrait = Trait( + name: "Tracing", + description: "Enable opt-in Swift <-> JavaScript bridge tracing hooks.", + enabledTraits: [] +) + +let testingLinkerFlags: [LinkerSetting] = [ + .unsafeFlags([ + "-Xlinker", "--stack-first", + "-Xlinker", "--global-base=524288", + "-Xlinker", "-z", + "-Xlinker", "stack-size=524288", + ]) +] + +let package = Package( + name: "JavaScriptKit", + platforms: [ + .macOS(.v13), + .iOS(.v13), + .tvOS(.v13), + .watchOS(.v6), + .macCatalyst(.v13), + ], + products: [ + .library(name: "JavaScriptKit", targets: ["JavaScriptKit"]), + .library(name: "JavaScriptEventLoop", targets: ["JavaScriptEventLoop"]), + .library(name: "JavaScriptBigIntSupport", targets: ["JavaScriptBigIntSupport"]), + .library(name: "JavaScriptFoundationCompat", targets: ["JavaScriptFoundationCompat"]), + .library(name: "JavaScriptEventLoopTestSupport", targets: ["JavaScriptEventLoopTestSupport"]), + .plugin(name: "PackageToJS", targets: ["PackageToJS"]), + .plugin(name: "BridgeJS", targets: ["BridgeJS"]), + .plugin(name: "BridgeJSCommandPlugin", targets: ["BridgeJSCommandPlugin"]), + ], + traits: [tracingTrait], + dependencies: [ + .package(url: "https://github.com/swiftlang/swift-syntax", "600.0.0"..<"603.0.0") + ], + targets: [ + .target( + name: "JavaScriptKit", + dependencies: ["_CJavaScriptKit", "BridgeJSMacros"], + exclude: useLegacyResourceBundling ? [] : ["Runtime"], + resources: useLegacyResourceBundling ? [.copy("Runtime")] : [], + cSettings: shouldBuildForEmbedded + ? [ + .unsafeFlags(["-fdeclspec"]) + ] : nil, + swiftSettings: [ + .enableExperimentalFeature("Extern"), + .define("Tracing", .when(traits: ["Tracing"])), + ] + + (enableTracingByEnv ? [.define("Tracing")] : []) + + (shouldBuildForEmbedded + ? [ + .enableExperimentalFeature("Embedded"), + .unsafeFlags(["-Xfrontend", "-emit-empty-object-file"]), + ] : []) + ), + .target(name: "_CJavaScriptKit"), + .macro( + name: "BridgeJSMacros", + dependencies: [ + .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), + .product(name: "SwiftCompilerPlugin", package: "swift-syntax"), + ] + ), + + .testTarget( + name: "JavaScriptKitTests", + dependencies: ["JavaScriptKit"], + swiftSettings: [ + .enableExperimentalFeature("Extern"), + .define("Tracing", .when(traits: ["Tracing"])), + ] + (enableTracingByEnv ? [.define("Tracing")] : []), + linkerSettings: testingLinkerFlags + ), + + .target( + name: "JavaScriptBigIntSupport", + dependencies: ["_CJavaScriptBigIntSupport", "JavaScriptKit"], + swiftSettings: shouldBuildForEmbedded + ? [ + .enableExperimentalFeature("Embedded"), + .unsafeFlags(["-Xfrontend", "-emit-empty-object-file"]), + ] : [] + ), + .target(name: "_CJavaScriptBigIntSupport", dependencies: ["_CJavaScriptKit"]), + .testTarget( + name: "JavaScriptBigIntSupportTests", + dependencies: ["JavaScriptBigIntSupport", "JavaScriptKit"], + linkerSettings: testingLinkerFlags + ), + + .target( + name: "JavaScriptEventLoop", + dependencies: ["JavaScriptKit", "_CJavaScriptEventLoop"], + swiftSettings: shouldBuildForEmbedded + ? [ + .enableExperimentalFeature("Embedded"), + .unsafeFlags(["-Xfrontend", "-emit-empty-object-file"]), + ] : [] + ), + .target(name: "_CJavaScriptEventLoop"), + .testTarget( + name: "JavaScriptEventLoopTests", + dependencies: [ + "JavaScriptEventLoop", + "JavaScriptKit", + "JavaScriptEventLoopTestSupport", + ], + swiftSettings: [ + .enableExperimentalFeature("Extern") + ], + linkerSettings: testingLinkerFlags + ), + .target( + name: "JavaScriptEventLoopTestSupport", + dependencies: [ + "_CJavaScriptEventLoopTestSupport", + "JavaScriptEventLoop", + ] + ), + .target(name: "_CJavaScriptEventLoopTestSupport"), + .testTarget( + name: "JavaScriptEventLoopTestSupportTests", + dependencies: [ + "JavaScriptKit", + "JavaScriptEventLoopTestSupport", + ], + linkerSettings: testingLinkerFlags + ), + .target( + name: "JavaScriptFoundationCompat", + dependencies: [ + "JavaScriptKit" + ] + ), + .testTarget( + name: "JavaScriptFoundationCompatTests", + dependencies: [ + "JavaScriptFoundationCompat" + ], + linkerSettings: testingLinkerFlags + ), + .plugin( + name: "PackageToJS", + capability: .command( + intent: .custom(verb: "js", description: "Convert a Swift package to a JavaScript package") + ), + path: "Plugins/PackageToJS/Sources" + ), + .plugin( + name: "BridgeJS", + capability: .buildTool(), + dependencies: ["BridgeJSTool"], + path: "Plugins/BridgeJS/Sources/BridgeJSBuildPlugin" + ), + .plugin( + name: "BridgeJSCommandPlugin", + capability: .command( + intent: .custom(verb: "bridge-js", description: "Generate bridging code"), + permissions: [.writeToPackageDirectory(reason: "Generate bridging code")] + ), + dependencies: ["BridgeJSTool"], + path: "Plugins/BridgeJS/Sources/BridgeJSCommandPlugin" + ), + .executableTarget( + name: "BridgeJSTool", + dependencies: [ + .product(name: "SwiftParser", package: "swift-syntax"), + .product(name: "SwiftSyntax", package: "swift-syntax"), + .product(name: "SwiftBasicFormat", package: "swift-syntax"), + .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), + ], + exclude: ["TS2Swift/JavaScript", "README.md"] + ), + .testTarget( + name: "BridgeJSRuntimeTests", + dependencies: ["JavaScriptKit", "JavaScriptEventLoop"], + exclude: [ + "bridge-js.config.json", + "bridge-js.d.ts", + "bridge-js.global.d.ts", + "Generated/JavaScript", + ], + swiftSettings: [ + .enableExperimentalFeature("Extern") + ], + linkerSettings: testingLinkerFlags + ), + .testTarget( + name: "BridgeJSGlobalTests", + dependencies: ["JavaScriptKit", "JavaScriptEventLoop"], + exclude: [ + "bridge-js.config.json", + "bridge-js.d.ts", + "Generated/JavaScript", + ], + swiftSettings: [ + .enableExperimentalFeature("Extern") + ], + linkerSettings: testingLinkerFlags + ), + ] +) diff --git a/Plugins/BridgeJS/Package.swift b/Plugins/BridgeJS/Package.swift index eb675c86b..a03172f17 100644 --- a/Plugins/BridgeJS/Package.swift +++ b/Plugins/BridgeJS/Package.swift @@ -3,11 +3,13 @@ import CompilerPluginSupport import PackageDescription +let swiftSyntaxVersion = Context.environment["BRIDGEJS_OVERRIDE_SWIFT_SYNTAX_VERSION"] ?? "600.0.1" + let package = Package( name: "BridgeJS", platforms: [.macOS(.v13)], dependencies: [ - .package(url: "https://github.com/swiftlang/swift-syntax", from: "600.0.1"), + .package(url: "https://github.com/swiftlang/swift-syntax", from: Version(swiftSyntaxVersion)!), // Development dependencies .package(url: "https://github.com/apple/swift-argument-parser", from: "1.7.0"), ], @@ -70,7 +72,7 @@ let package = Package( name: "BridgeJSMacrosTests", dependencies: [ "BridgeJSMacros", - .product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"), + .product(name: "SwiftSyntaxMacrosGenericTestSupport", package: "swift-syntax"), ] ), diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index a40f9c2b6..d7d5c8200 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -74,7 +74,7 @@ public class ExportSwift { let structCodegen = StructCodegen() for structDef in skeleton.structs { - decls.append(structCodegen.renderStructHelpers(structDef)) + decls.append(contentsOf: structCodegen.renderStructHelpers(structDef)) decls.append(contentsOf: try renderSingleExportedStruct(struct: structDef)) } @@ -130,10 +130,43 @@ public class ExportSwift { case .swiftStruct(let structName): typeNameForIntrinsic = structName liftingExpr = ExprSyntax("\(raw: structName).bridgeJSLiftParameter()") + case .array: + typeNameForIntrinsic = param.type.swiftType + liftingExpr = StackCodegen().liftExpression(for: param.type) case .optional(let wrappedType): - typeNameForIntrinsic = "Optional<\(wrappedType.swiftType)>" + if case .array(let elementType) = wrappedType { + let arrayLift = StackCodegen().liftArrayExpression(elementType: elementType) + let isSomeParam = argumentsToLift[0] + let swiftTypeName = elementType.swiftType + typeNameForIntrinsic = "Optional<[\(swiftTypeName)]>" + liftingExpr = ExprSyntax( + """ + { + if \(raw: isSomeParam) == 0 { + return Optional<[\(raw: swiftTypeName)]>.none + } else { + return \(arrayLift) + } + }() + """ + ) + } else if case .swiftProtocol(let protocolName) = wrappedType { + let wrapperName = "Any\(protocolName)" + typeNameForIntrinsic = "Optional<\(wrapperName)>" + liftingExpr = ExprSyntax( + "\(raw: typeNameForIntrinsic).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" + ) + } else { + typeNameForIntrinsic = "Optional<\(wrappedType.swiftType)>" + liftingExpr = ExprSyntax( + "\(raw: typeNameForIntrinsic).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" + ) + } + case .swiftProtocol(let protocolName): + let wrapperName = "Any\(protocolName)" + typeNameForIntrinsic = wrapperName liftingExpr = ExprSyntax( - "\(raw: typeNameForIntrinsic).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" + "\(raw: wrapperName).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" ) default: typeNameForIntrinsic = param.type.swiftType @@ -246,7 +279,8 @@ public class ExportSwift { let stackParamIndices = parameters.enumerated().compactMap { index, param -> Int? in switch param.type { case .swiftStruct, .optional(.swiftStruct), - .associatedValueEnum, .optional(.associatedValueEnum): + .associatedValueEnum, .optional(.associatedValueEnum), + .array: return index default: return nil @@ -319,9 +353,15 @@ public class ExportSwift { return } - if case .closure(let signature) = returnType { + switch returnType { + case .closure(let signature): append("return _BJS_Closure_\(raw: signature.mangleName).bridgeJSLower(ret)") - } else { + case .array, .optional(.array): + let stackCodegen = StackCodegen() + for stmt in stackCodegen.lowerStatements(for: returnType, accessor: "ret", varPrefix: "ret") { + append(stmt) + } + default: append("return ret.bridgeJSLowerReturn()") } } @@ -759,34 +799,41 @@ struct StackCodegen { func liftExpression(for type: BridgeType) -> ExprSyntax { switch type { case .string: - return "String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())" - case .int: - return "Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())" + return "String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())" + case .int, .uint: + return "Int.bridgeJSLiftParameter(_swift_js_pop_i32())" case .bool: - return "Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32())" + return "Bool.bridgeJSLiftParameter(_swift_js_pop_i32())" case .float: - return "Float.bridgeJSLiftParameter(_swift_js_pop_param_f32())" + return "Float.bridgeJSLiftParameter(_swift_js_pop_f32())" case .double: - return "Double.bridgeJSLiftParameter(_swift_js_pop_param_f64())" + return "Double.bridgeJSLiftParameter(_swift_js_pop_f64())" case .jsObject: - return "JSObject.bridgeJSLiftParameter(_swift_js_pop_param_int32())" + return "JSObject.bridgeJSLiftParameter(_swift_js_pop_i32())" case .swiftHeapObject(let className): - return "\(raw: className).bridgeJSLiftParameter(_swift_js_pop_param_pointer())" - case .swiftProtocol: - // Protocols are handled via JSObject - return "JSObject.bridgeJSLiftParameter(_swift_js_pop_param_int32())" + return "\(raw: className).bridgeJSLiftParameter(_swift_js_pop_pointer())" + case .unsafePointer: + return "\(raw: type.swiftType).bridgeJSLiftParameter(_swift_js_pop_pointer())" + case .swiftProtocol(let protocolName): + // Protocols use their Any wrapper type for lifting + let wrapperName = "Any\(protocolName)" + return "\(raw: wrapperName).bridgeJSLiftParameter(_swift_js_pop_i32())" case .caseEnum(let enumName): - return "\(raw: enumName).bridgeJSLiftParameter(_swift_js_pop_param_int32())" + return "\(raw: enumName).bridgeJSLiftParameter(_swift_js_pop_i32())" case .rawValueEnum(let enumName, let rawType): switch rawType { case .string: return - "\(raw: enumName).bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())" - case .bool, .int, .int32, .int64, .uint, .uint32, .uint64, .float, .double: - return "\(raw: enumName).bridgeJSLiftParameter(_swift_js_pop_param_int32())" + "\(raw: enumName).bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())" + case .float: + return "\(raw: enumName).bridgeJSLiftParameter(_swift_js_pop_f32())" + case .double: + return "\(raw: enumName).bridgeJSLiftParameter(_swift_js_pop_f64())" + case .bool, .int, .int32, .int64, .uint, .uint32, .uint64: + return "\(raw: enumName).bridgeJSLiftParameter(_swift_js_pop_i32())" } case .associatedValueEnum(let enumName): - return "\(raw: enumName).bridgeJSLiftParameter(_swift_js_pop_param_int32())" + return "\(raw: enumName).bridgeJSLiftParameter(_swift_js_pop_i32())" case .swiftStruct(let structName): return "\(raw: structName).bridgeJSLiftParameter()" case .optional(let wrappedType): @@ -798,48 +845,86 @@ struct StackCodegen { // Namespace enums are not passed as values return "()" case .closure: - return "JSObject.bridgeJSLiftParameter(_swift_js_pop_param_int32())" + return "JSObject.bridgeJSLiftParameter(_swift_js_pop_i32())" + case .array(let elementType): + return liftArrayExpression(elementType: elementType) } } + func liftArrayExpression(elementType: BridgeType) -> ExprSyntax { + let elementLift = liftExpression(for: elementType) + let swiftTypeName = elementType.swiftType + return """ + { + let __count = Int(_swift_js_pop_i32()) + var __result: [\(raw: swiftTypeName)] = [] + __result.reserveCapacity(__count) + for _ in 0..<__count { + __result.append(\(elementLift)) + } + __result.reverse() + return __result + }() + """ + } + private func liftOptionalExpression(wrappedType: BridgeType) -> ExprSyntax { switch wrappedType { case .string: return - "Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32(), _swift_js_pop_param_int32())" - case .int: - return "Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())" + "Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32(), _swift_js_pop_i32())" + case .int, .uint: + return "Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())" case .bool: - return "Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())" + return "Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())" case .float: - return "Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_f32())" + return "Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_f32())" case .double: - return "Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_f64())" + return "Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_f64())" case .caseEnum(let enumName): return - "Optional<\(raw: enumName)>.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())" + "Optional<\(raw: enumName)>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())" case .rawValueEnum(let enumName, let rawType): switch rawType { case .string: return - "Optional<\(raw: enumName)>.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32(), _swift_js_pop_param_int32())" - case .bool, .int, .float, .double, .int32, .int64, .uint, .uint32, .uint64: + "Optional<\(raw: enumName)>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32(), _swift_js_pop_i32())" + case .float: + return + "Optional<\(raw: enumName)>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_f32())" + case .double: return - "Optional<\(raw: enumName)>.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())" + "Optional<\(raw: enumName)>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_f64())" + case .bool, .int, .int32, .int64, .uint, .uint32, .uint64: + return + "Optional<\(raw: enumName)>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())" } case .swiftStruct(let nestedName): - return "Optional<\(raw: nestedName)>.bridgeJSLiftParameter(_swift_js_pop_param_int32())" + return "Optional<\(raw: nestedName)>.bridgeJSLiftParameter(_swift_js_pop_i32())" case .swiftHeapObject(let className): return - "Optional<\(raw: className)>.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_pointer())" + "Optional<\(raw: className)>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_pointer())" case .associatedValueEnum(let enumName): return - "Optional<\(raw: enumName)>.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())" + "Optional<\(raw: enumName)>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())" case .jsObject: - return "Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())" + return "Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())" + case .array(let elementType): + let arrayLift = liftArrayExpression(elementType: elementType) + let swiftTypeName = elementType.swiftType + return """ + { + let __isSome = _swift_js_pop_i32() + if __isSome == 0 { + return Optional<[\(raw: swiftTypeName)]>.none + } else { + return \(arrayLift) + } + }() + """ default: // Fallback for other optional types - return "Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())" + return "Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())" } } @@ -860,24 +945,39 @@ struct StackCodegen { "var __bjs_\(raw: varPrefix) = \(raw: accessor)", "__bjs_\(raw: varPrefix).withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) }", ] - case .int: - return ["_swift_js_push_int(Int32(\(raw: accessor)))"] + case .int, .uint: + return ["_swift_js_push_i32(Int32(\(raw: accessor)))"] case .bool: - return ["_swift_js_push_int(\(raw: accessor) ? 1 : 0)"] + return ["_swift_js_push_i32(\(raw: accessor) ? 1 : 0)"] case .float: return ["_swift_js_push_f32(\(raw: accessor))"] case .double: return ["_swift_js_push_f64(\(raw: accessor))"] case .jsObject: - return ["_swift_js_push_int(\(raw: accessor).bridgeJSLowerParameter())"] + return ["_swift_js_push_i32(\(raw: accessor).bridgeJSLowerReturn())"] case .swiftHeapObject: return ["_swift_js_push_pointer(\(raw: accessor).bridgeJSLowerReturn())"] - case .swiftProtocol: - return ["_swift_js_push_int(\(raw: accessor).bridgeJSLowerParameter())"] + case .unsafePointer: + return ["_swift_js_push_pointer(\(raw: accessor).bridgeJSLowerReturn())"] + case .swiftProtocol(let protocolName): + let wrapperName = "Any\(protocolName)" + return ["_swift_js_push_i32((\(raw: accessor) as! \(raw: wrapperName)).bridgeJSLowerReturn())"] case .caseEnum: - return ["_swift_js_push_int(Int32(\(raw: accessor).bridgeJSLowerParameter()))"] - case .rawValueEnum: - return ["_swift_js_push_int(Int32(\(raw: accessor).bridgeJSLowerParameter()))"] + return ["_swift_js_push_i32(Int32(\(raw: accessor).bridgeJSLowerParameter()))"] + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: + return [ + "var __bjs_\(raw: varPrefix) = \(raw: accessor).rawValue", + "__bjs_\(raw: varPrefix).withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) }", + ] + case .float: + return ["_swift_js_push_f32(\(raw: accessor).bridgeJSLowerParameter())"] + case .double: + return ["_swift_js_push_f64(\(raw: accessor).bridgeJSLowerParameter())"] + default: + return ["_swift_js_push_i32(Int32(\(raw: accessor).bridgeJSLowerParameter()))"] + } case .associatedValueEnum: return ["\(raw: accessor).bridgeJSLowerReturn()"] case .swiftStruct: @@ -890,9 +990,34 @@ struct StackCodegen { return [] case .closure: return ["_swift_js_push_pointer(\(raw: accessor).bridgeJSLowerReturn())"] + case .array(let elementType): + return lowerArrayStatements(elementType: elementType, accessor: accessor, varPrefix: varPrefix) } } + private func lowerArrayStatements( + elementType: BridgeType, + accessor: String, + varPrefix: String + ) -> [CodeBlockItemSyntax] { + var statements: [CodeBlockItemSyntax] = [] + let elementVarName = "__bjs_elem_\(varPrefix)" + statements.append("for \(raw: elementVarName) in \(raw: accessor) {") + + let elementStatements = lowerStatements( + for: elementType, + accessor: elementVarName, + varPrefix: "\(varPrefix)_elem" + ) + for stmt in elementStatements { + statements.append(stmt) + } + + statements.append("}") + statements.append("_swift_js_push_i32(Int32(\(raw: accessor).count))") + return statements + } + private func lowerOptionalStatements( wrappedType: BridgeType, accessor: String, @@ -912,7 +1037,7 @@ struct StackCodegen { } statements.append("}") - statements.append("_swift_js_push_int(__bjs_isSome_\(raw: varPrefix) ? 1 : 0)") + statements.append("_swift_js_push_i32(__bjs_isSome_\(raw: varPrefix) ? 1 : 0)") return statements } @@ -927,16 +1052,16 @@ struct StackCodegen { "var __bjs_str_\(raw: varPrefix) = \(raw: unwrappedVar)", "__bjs_str_\(raw: varPrefix).withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) }", ] - case .int: - return ["_swift_js_push_int(Int32(\(raw: unwrappedVar)))"] + case .int, .uint: + return ["_swift_js_push_i32(Int32(\(raw: unwrappedVar)))"] case .bool: - return ["_swift_js_push_int(\(raw: unwrappedVar) ? 1 : 0)"] + return ["_swift_js_push_i32(\(raw: unwrappedVar) ? 1 : 0)"] case .float: return ["_swift_js_push_f32(\(raw: unwrappedVar))"] case .double: return ["_swift_js_push_f64(\(raw: unwrappedVar))"] case .caseEnum: - return ["_swift_js_push_int(\(raw: unwrappedVar).bridgeJSLowerParameter())"] + return ["_swift_js_push_i32(\(raw: unwrappedVar).bridgeJSLowerParameter())"] case .rawValueEnum(_, let rawType): switch rawType { case .string: @@ -944,17 +1069,23 @@ struct StackCodegen { "var __bjs_str_\(raw: varPrefix) = \(raw: unwrappedVar).rawValue", "__bjs_str_\(raw: varPrefix).withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) }", ] + case .float: + return ["_swift_js_push_f32(\(raw: unwrappedVar).bridgeJSLowerParameter())"] + case .double: + return ["_swift_js_push_f64(\(raw: unwrappedVar).bridgeJSLowerParameter())"] default: - return ["_swift_js_push_int(\(raw: unwrappedVar).bridgeJSLowerParameter())"] + return ["_swift_js_push_i32(\(raw: unwrappedVar).bridgeJSLowerParameter())"] } case .swiftStruct: return ["\(raw: unwrappedVar).bridgeJSLowerReturn()"] case .swiftHeapObject: return ["_swift_js_push_pointer(\(raw: unwrappedVar).bridgeJSLowerReturn())"] case .associatedValueEnum: - return ["_swift_js_push_int(\(raw: unwrappedVar).bridgeJSLowerParameter())"] + return ["_swift_js_push_i32(\(raw: unwrappedVar).bridgeJSLowerParameter())"] case .jsObject: - return ["_swift_js_push_int(\(raw: unwrappedVar).bridgeJSLowerParameter())"] + return ["_swift_js_push_i32(\(raw: unwrappedVar).bridgeJSLowerReturn())"] + case .array(let elementType): + return lowerArrayStatements(elementType: elementType, accessor: unwrappedVar, varPrefix: varPrefix) default: return ["preconditionFailure(\"BridgeJS: unsupported optional wrapped type\")"] } @@ -1147,12 +1278,18 @@ struct EnumCodegen { struct StructCodegen { private let stackCodegen = StackCodegen() - func renderStructHelpers(_ structDef: ExportedStruct) -> DeclSyntax { + 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) " } ?? "" - return """ + 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")) @@ -1161,8 +1298,71 @@ struct StructCodegen { @_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() + } + + \(raw: accessControl)func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: \(raw: liftFunctionName)())) + } } """ + + let lowerExternDecl = Self.renderStructExtern( + externName: lowerExternName, + functionName: lowerFunctionName, + signature: SwiftSignatureBuilder.buildABIFunctionSignature( + abiParameters: [("objectId", .i32)], + returnType: .i32 + ) + ) + let liftExternDecl = Self.renderStructExtern( + externName: liftExternName, + functionName: liftFunctionName, + signature: SwiftSignatureBuilder.buildABIFunctionSignature( + abiParameters: [], + returnType: .i32 + ) + ) + + return [bridgedStructExtension, lowerExternDecl, liftExternDecl] + } + + private static func renderStructExtern( + 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)) + }, + funcKeyword: .keyword(.func), + name: .identifier(functionName), + signature: signature, + body: CodeBlockSyntax { + "fatalError(\"Only available on WebAssembly\")" + } + ) + + return DeclSyntax( + SwiftCodePattern.buildWasmConditionalCompilationDecls( + wasmDecl: DeclSyntax(externFuncDecl), + elseDecl: DeclSyntax(stubFuncDecl) + ) + ) } private func generateStructLiftCode(structDef: ExportedStruct) -> [String] { @@ -1421,20 +1621,40 @@ extension WasmCoreType { } } +extension UnsafePointerType { + var swiftType: String { + switch kind { + case .unsafePointer: + return "UnsafePointer<\(pointee ?? "Never")>" + case .unsafeMutablePointer: + return "UnsafeMutablePointer<\(pointee ?? "Never")>" + case .unsafeRawPointer: + return "UnsafeRawPointer" + case .unsafeMutableRawPointer: + return "UnsafeMutableRawPointer" + case .opaquePointer: + return "OpaquePointer" + } + } +} + extension BridgeType { var swiftType: String { switch self { case .bool: return "Bool" case .int: return "Int" + case .uint: return "UInt" case .float: return "Float" case .double: return "Double" case .string: return "String" case .jsObject(nil): return "JSObject" case .jsObject(let name?): return name case .swiftHeapObject(let name): return name + case .unsafePointer(let ptr): return ptr.swiftType case .swiftProtocol(let name): return "Any\(name)" case .void: return "Void" case .optional(let wrappedType): return "Optional<\(wrappedType.swiftType)>" + case .array(let elementType): return "[\(elementType.swiftType)]" case .caseEnum(let name): return name case .rawValueEnum(let name, _): return name case .associatedValueEnum(let name): return name @@ -1457,6 +1677,7 @@ extension BridgeType { static let string = LiftingIntrinsicInfo(parameters: [("bytes", .i32), ("length", .i32)]) static let jsObject = LiftingIntrinsicInfo(parameters: [("value", .i32)]) static let swiftHeapObject = LiftingIntrinsicInfo(parameters: [("value", .pointer)]) + static let unsafePointer = LiftingIntrinsicInfo(parameters: [("pointer", .pointer)]) static let void = LiftingIntrinsicInfo(parameters: []) static let caseEnum = LiftingIntrinsicInfo(parameters: [("value", .i32)]) static let associatedValueEnum = LiftingIntrinsicInfo(parameters: [ @@ -1467,12 +1688,13 @@ extension BridgeType { func liftParameterInfo() throws -> LiftingIntrinsicInfo { switch self { case .bool: return .bool - case .int: return .int + case .int, .uint: return .int case .float: return .float case .double: return .double case .string: return .string case .jsObject: return .jsObject case .swiftHeapObject: return .swiftHeapObject + case .unsafePointer: return .unsafePointer case .swiftProtocol: return .jsObject case .void: return .void case .optional(let wrappedType): @@ -1490,6 +1712,8 @@ extension BridgeType { throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters") case .closure: return LiftingIntrinsicInfo(parameters: [("callbackId", .i32)]) + case .array: + return LiftingIntrinsicInfo(parameters: []) } } @@ -1503,23 +1727,26 @@ extension BridgeType { static let string = LoweringIntrinsicInfo(returnType: nil) static let jsObject = LoweringIntrinsicInfo(returnType: .i32) static let swiftHeapObject = LoweringIntrinsicInfo(returnType: .pointer) + static let unsafePointer = LoweringIntrinsicInfo(returnType: .pointer) static let void = LoweringIntrinsicInfo(returnType: nil) static let caseEnum = LoweringIntrinsicInfo(returnType: .i32) static let rawValueEnum = LoweringIntrinsicInfo(returnType: .i32) static let associatedValueEnum = LoweringIntrinsicInfo(returnType: nil) static let swiftStruct = LoweringIntrinsicInfo(returnType: nil) static let optional = LoweringIntrinsicInfo(returnType: nil) + static let array = LoweringIntrinsicInfo(returnType: nil) } func loweringReturnInfo() throws -> LoweringIntrinsicInfo { switch self { case .bool: return .bool - case .int: return .int + case .int, .uint: return .int case .float: return .float case .double: return .double case .string: return .string case .jsObject: return .jsObject case .swiftHeapObject: return .swiftHeapObject + case .unsafePointer: return .unsafePointer case .swiftProtocol: return .jsObject case .void: return .void case .optional: return .optional @@ -1534,6 +1761,8 @@ extension BridgeType { throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters") case .closure: return .swiftHeapObject + case .array: + return .array } } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift index dd6c9d27a..7c391eea0 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift @@ -760,10 +760,11 @@ enum SwiftCodePattern { return AttributeListSyntax { #if canImport(SwiftSyntax602) let exposeAttrArgs = AttributeSyntax.Arguments.argumentList( - [ - LabeledExprSyntax(label: nil, expression: DeclReferenceExprSyntax(baseName: "wasm")), - LabeledExprSyntax(label: nil, expression: StringLiteralExprSyntax(content: abiName)), - ] + LabeledExprListSyntax { + LabeledExprSyntax(label: nil, expression: DeclReferenceExprSyntax(baseName: "wasm")) + .with(\.trailingComma, .commaToken()) + LabeledExprSyntax(label: nil, expression: StringLiteralExprSyntax(content: abiName)) + } ) let cdeclAttrArgs = AttributeSyntax.Arguments.argumentList( [ @@ -866,7 +867,7 @@ extension BridgeType { func loweringParameterInfo(context: BridgeContext = .importTS) throws -> LoweringParameterInfo { switch self { case .bool: return .bool - case .int: return .int + case .int, .uint: return .int case .float: return .float case .double: return .double case .string: return .string @@ -875,6 +876,8 @@ extension BridgeType { case .closure: // Swift closure is boxed and passed to JS as a pointer. return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)]) + case .unsafePointer: + return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)]) case .swiftHeapObject(let className): switch context { case .importTS: @@ -914,7 +917,8 @@ extension BridgeType { case .swiftStruct: switch context { case .importTS: - throw BridgeJSCoreError("Swift structs are not yet supported in TypeScript imports") + // Swift structs are bridged as JS objects (object IDs) in imported signatures. + return LoweringParameterInfo(loweredParameters: [("objectId", .i32)]) case .exportSwift: return LoweringParameterInfo(loweredParameters: []) } @@ -930,6 +934,13 @@ extension BridgeType { params.append(contentsOf: wrappedInfo.loweredParameters) return LoweringParameterInfo(loweredParameters: params) } + case .array: + switch context { + case .importTS: + throw BridgeJSCoreError("Array types are not yet supported in TypeScript imports") + case .exportSwift: + return LoweringParameterInfo(loweredParameters: []) + } } } @@ -950,7 +961,7 @@ extension BridgeType { ) throws -> LiftingReturnInfo { switch self { case .bool: return .bool - case .int: return .int + case .int, .uint: return .int case .float: return .float case .double: return .double case .string: return .string @@ -959,6 +970,8 @@ extension BridgeType { case .closure: // JS returns a callback ID for closures, which Swift lifts to a typed closure. return LiftingReturnInfo(valueToLift: .i32) + case .unsafePointer: + return LiftingReturnInfo(valueToLift: .pointer) case .swiftHeapObject(let className): switch context { case .importTS: @@ -998,7 +1011,8 @@ extension BridgeType { case .swiftStruct: switch context { case .importTS: - throw BridgeJSCoreError("Swift structs are not yet supported in TypeScript imports") + // Swift structs are bridged as JS objects (object IDs) in imported signatures. + return LiftingReturnInfo(valueToLift: .i32) case .exportSwift: return LiftingReturnInfo(valueToLift: nil) } @@ -1012,6 +1026,13 @@ extension BridgeType { let wrappedInfo = try wrappedType.liftingReturnInfo(context: context) return LiftingReturnInfo(valueToLift: wrappedInfo.valueToLift) } + case .array: + switch context { + case .importTS: + throw BridgeJSCoreError("Array types are not yet supported in TypeScript imports") + case .exportSwift: + return LiftingReturnInfo(valueToLift: nil) + } } } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift index f18788e7d..ea79d3f3b 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift @@ -157,12 +157,47 @@ public final class SwiftToSkeleton { return .optional(wrappedType) } } + // [T] + if let arrayType = type.as(ArrayTypeSyntax.self) { + if let elementType = lookupType(for: arrayType.element, errors: &errors) { + return .array(elementType) + } + } + // Array + if let identifierType = type.as(IdentifierTypeSyntax.self), + identifierType.name.text == "Array", + let genericArgs = identifierType.genericArgumentClause?.arguments, + genericArgs.count == 1, + let argType = TypeSyntax(genericArgs.first?.argument) + { + if let elementType = lookupType(for: argType, errors: &errors) { + return .array(elementType) + } + } + // Swift.Array + if let memberType = type.as(MemberTypeSyntax.self), + let baseType = memberType.baseType.as(IdentifierTypeSyntax.self), + baseType.name.text == "Swift", + memberType.name.text == "Array", + let genericArgs = memberType.genericArgumentClause?.arguments, + genericArgs.count == 1, + let argType = TypeSyntax(genericArgs.first?.argument) + { + if let elementType = lookupType(for: argType, errors: &errors) { + return .array(elementType) + } + } if let aliasDecl = typeDeclResolver.resolveTypeAlias(type) { if let resolvedType = lookupType(for: aliasDecl.initializer.value, errors: &errors) { return resolvedType } } + // UnsafePointer family + if let unsafePointerType = Self.parseUnsafePointerType(type) { + return .unsafePointer(unsafePointerType) + } + let typeName: String if let identifier = type.as(IdentifierTypeSyntax.self) { typeName = Self.normalizeIdentifier(identifier.name.text) @@ -248,6 +283,55 @@ public final class SwiftToSkeleton { return .swiftHeapObject(swiftCallName) } + fileprivate static func parseUnsafePointerType(_ type: TypeSyntax) -> UnsafePointerType? { + func parse(baseName: String, genericArg: TypeSyntax?) -> UnsafePointerType? { + let pointee = genericArg?.trimmedDescription + switch baseName { + case "UnsafePointer": + return .init(kind: .unsafePointer, pointee: pointee) + case "UnsafeMutablePointer": + return .init(kind: .unsafeMutablePointer, pointee: pointee) + case "UnsafeRawPointer": + return .init(kind: .unsafeRawPointer) + case "UnsafeMutableRawPointer": + return .init(kind: .unsafeMutableRawPointer) + case "OpaquePointer": + return .init(kind: .opaquePointer) + default: + return nil + } + } + + if let identifier = type.as(IdentifierTypeSyntax.self) { + let baseName = identifier.name.text + if (baseName == "UnsafePointer" || baseName == "UnsafeMutablePointer"), + let genericArgs = identifier.genericArgumentClause?.arguments, + genericArgs.count == 1, + let argType = TypeSyntax(genericArgs.first?.argument) + { + return parse(baseName: baseName, genericArg: argType) + } + return parse(baseName: baseName, genericArg: nil) + } + + if let member = type.as(MemberTypeSyntax.self), + let base = member.baseType.as(IdentifierTypeSyntax.self), + base.name.text == "Swift" + { + let baseName = member.name.text + if (baseName == "UnsafePointer" || baseName == "UnsafeMutablePointer"), + let genericArgs = member.genericArgumentClause?.arguments, + genericArgs.count == 1, + let argType = TypeSyntax(genericArgs.first?.argument) + { + return parse(baseName: baseName, genericArg: argType) + } + return parse(baseName: baseName, genericArg: nil) + } + + return nil + } + /// Computes the full Swift call name by walking up the AST hierarchy to find all parent enums /// This generates the qualified name needed for Swift code generation (e.g., "Networking.API.HTTPServer") fileprivate static func computeSwiftCallName(for node: some SyntaxProtocol, itemName: String) -> String { @@ -425,7 +509,7 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { let expression = initClause.value // Function calls are checked later in extractDefaultValue (as constructors are allowed) - if expression.is(ArrayExprSyntax.self) { return false } + // Array literals are allowed but checked in extractArrayDefaultValue if expression.is(DictionaryExprSyntax.self) { return false } if expression.is(BinaryOperatorExprSyntax.self) { return false } if expression.is(ClosureExprSyntax.self) { return false } @@ -521,6 +605,10 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { return extractConstructorDefaultValue(from: funcCall, type: type) } + if let arrayExpr = expr.as(ArrayExprSyntax.self) { + return extractArrayDefaultValue(from: arrayExpr, type: type) + } + if let literalValue = extractLiteralValue(from: expr, type: type) { return literalValue } @@ -681,6 +769,43 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { return nil } + /// Extracts default value from an array literal expression + private func extractArrayDefaultValue( + from arrayExpr: ArrayExprSyntax, + type: BridgeType + ) -> DefaultValue? { + // Verify the type is an array type + let elementType: BridgeType? + switch type { + case .array(let element): + elementType = element + case .optional(.array(let element)): + elementType = element + default: + diagnose( + node: arrayExpr, + message: "Array literal is only valid for array parameters", + hint: "Parameter type should be an array like [Int] or [String]" + ) + return nil + } + + var elements: [DefaultValue] = [] + for element in arrayExpr.elements { + guard let elementValue = extractLiteralValue(from: element.expression, type: elementType) else { + diagnose( + node: element.expression, + message: "Array element must be a literal value", + hint: "Use simple literals like \"text\", 42, true, false in array elements" + ) + return nil + } + elements.append(elementValue) + } + + return .array(elements) + } + /// Shared parameter parsing logic used by functions, initializers, and protocol methods private func parseParameters( from parameterClause: FunctionParameterClauseSyntax, @@ -1743,6 +1868,8 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { // Current type being collected (when in jsClassBody state) private struct CurrentType { let name: String + let jsName: String? + let from: JSImportFrom? var constructor: ImportedConstructorSkeleton? var methods: [ImportedFunctionSkeleton] var getters: [ImportedGetterSkeleton] @@ -1758,10 +1885,22 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { hasAttribute(attributes, name: "JSFunction") } + static func firstJSFunctionAttribute(_ attributes: AttributeListSyntax?) -> AttributeSyntax? { + attributes?.first { attribute in + attribute.as(AttributeSyntax.self)?.attributeName.trimmedDescription == "JSFunction" + }?.as(AttributeSyntax.self) + } + static func hasJSGetterAttribute(_ attributes: AttributeListSyntax?) -> Bool { hasAttribute(attributes, name: "JSGetter") } + static func firstJSGetterAttribute(_ attributes: AttributeListSyntax?) -> AttributeSyntax? { + attributes?.first { attribute in + attribute.as(AttributeSyntax.self)?.attributeName.trimmedDescription == "JSGetter" + }?.as(AttributeSyntax.self) + } + static func hasJSSetterAttribute(_ attributes: AttributeListSyntax?) -> Bool { hasAttribute(attributes, name: "JSSetter") } @@ -1776,6 +1915,12 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { hasAttribute(attributes, name: "JSClass") } + static func firstJSClassAttribute(_ attributes: AttributeListSyntax?) -> AttributeSyntax? { + attributes?.first { attribute in + attribute.as(AttributeSyntax.self)?.attributeName.trimmedDescription == "JSClass" + }?.as(AttributeSyntax.self) + } + static func hasAttribute(_ attributes: AttributeListSyntax?, name: String) -> Bool { guard let attributes else { return false } return attributes.contains { attribute in @@ -1784,7 +1929,7 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { } } - /// Extracts the jsName argument value from a @JSSetter attribute, if present. + /// Extracts the `jsName` argument value from an attribute, if present. static func extractJSName(from attribute: AttributeSyntax) -> String? { guard let arguments = attribute.arguments?.as(LabeledExprListSyntax.self) else { return nil @@ -1799,6 +1944,22 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { } return nil } + + /// Extracts the `from` argument value from an attribute, if present. + static func extractJSImportFrom(from attribute: AttributeSyntax) -> JSImportFrom? { + guard let arguments = attribute.arguments?.as(LabeledExprListSyntax.self) else { + return nil + } + for argument in arguments { + guard argument.label?.text == "from" else { continue } + + // Accept `.global`, `JSImportFrom.global`, etc. + let description = argument.expression.trimmedDescription + let caseName = description.split(separator: ".").last.map(String.init) ?? description + return JSImportFrom(rawValue: caseName) + } + return nil + } } // MARK: - Validation Helpers @@ -1883,22 +2044,15 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { // MARK: - Property Name Resolution - /// Helper for resolving property names from setter function names and jsName attributes + /// Helper for resolving property names from setter function names. private struct PropertyNameResolver { - /// Resolves property name and function base name from a setter function and optional jsName - /// - Returns: (propertyName, functionBaseName) where propertyName preserves case for getter matching, - /// and functionBaseName has lowercase first char for ABI generation + /// Resolves property name and function base name from a setter function. + /// - Returns: (propertyName, functionBaseName) where `propertyName` is derived from the setter name, + /// and `functionBaseName` has lowercase first char for ABI generation. static func resolve( functionName: String, - jsName: String?, normalizeIdentifier: (String) -> String ) -> (propertyName: String, functionBaseName: String)? { - if let jsName = jsName { - let propertyName = normalizeIdentifier(jsName) - let functionBaseName = propertyName.prefix(1).lowercased() + propertyName.dropFirst() - return (propertyName: propertyName, functionBaseName: functionBaseName) - } - let rawFunctionName = functionName.hasPrefix("`") && functionName.hasSuffix("`") && functionName.count > 2 ? String(functionName.dropFirst().dropLast()) @@ -1930,7 +2084,28 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { private func enterJSClass(_ typeName: String) { stateStack.append(.jsClassBody(name: typeName)) - currentType = CurrentType(name: typeName, constructor: nil, methods: [], getters: [], setters: []) + currentType = CurrentType( + name: typeName, + jsName: nil, + from: nil, + constructor: nil, + methods: [], + getters: [], + setters: [] + ) + } + + private func enterJSClass(_ typeName: String, jsName: String?, from: JSImportFrom?) { + stateStack.append(.jsClassBody(name: typeName)) + currentType = CurrentType( + name: typeName, + jsName: jsName, + from: from, + constructor: nil, + methods: [], + getters: [], + setters: [] + ) } private func exitJSClass() { @@ -1938,6 +2113,8 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { importedTypes.append( ImportedTypeSkeleton( name: type.name, + jsName: type.jsName, + from: type.from, constructor: type.constructor, methods: type.methods, getters: type.getters, @@ -1952,7 +2129,10 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { if AttributeChecker.hasJSClassAttribute(node.attributes) { - enterJSClass(node.name.text) + let attribute = AttributeChecker.firstJSClassAttribute(node.attributes) + let jsName = attribute.flatMap(AttributeChecker.extractJSName) + let from = attribute.flatMap(AttributeChecker.extractJSImportFrom) + enterJSClass(node.name.text, jsName: jsName, from: from) } return .visitChildren } @@ -1965,7 +2145,10 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { if AttributeChecker.hasJSClassAttribute(node.attributes) { - enterJSClass(node.name.text) + let attribute = AttributeChecker.firstJSClassAttribute(node.attributes) + let jsName = attribute.flatMap(AttributeChecker.extractJSName) + let from = attribute.flatMap(AttributeChecker.extractJSImportFrom) + enterJSClass(node.name.text, jsName: jsName, from: from) } return .visitChildren } @@ -2003,8 +2186,8 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { } private func handleTopLevelFunction(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind { - if AttributeChecker.hasJSFunctionAttribute(node.attributes), - let function = parseFunction(node, enclosingTypeName: nil, isStaticMember: true) + if let jsFunction = AttributeChecker.firstJSFunctionAttribute(node.attributes), + let function = parseFunction(jsFunction, node, enclosingTypeName: nil, isStaticMember: true) { importedFunctions.append(function) return .skipChildren @@ -2028,13 +2211,13 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { isStaticMember: Bool, type: inout CurrentType ) -> Bool { - if AttributeChecker.hasJSFunctionAttribute(node.attributes) { + if let jsFunction = AttributeChecker.firstJSFunctionAttribute(node.attributes) { if isStaticMember { - parseFunction(node, enclosingTypeName: typeName, isStaticMember: true).map { + parseFunction(jsFunction, node, enclosingTypeName: typeName, isStaticMember: true).map { importedFunctions.append($0) } } else { - parseFunction(node, enclosingTypeName: typeName, isStaticMember: false).map { + parseFunction(jsFunction, node, enclosingTypeName: typeName, isStaticMember: false).map { type.methods.append($0) } } @@ -2065,10 +2248,13 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { guard AttributeChecker.hasJSGetterAttribute(node.attributes) else { return .visitChildren } + guard let jsGetter = AttributeChecker.firstJSGetterAttribute(node.attributes) else { + return .skipChildren + } switch state { case .topLevel: - if let getter = parseGetterSkeleton(node) { + if let getter = parseGetterSkeleton(jsGetter, node) { importedGlobalGetters.append(getter) } return .skipChildren @@ -2085,7 +2271,7 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { "@JSGetter is not supported for static members. Use it only for instance members in @JSClass types." ) ) - } else if let getter = parseGetterSkeleton(node) { + } else if let getter = parseGetterSkeleton(jsGetter, node) { type.getters.append(getter) currentType = type } @@ -2128,8 +2314,8 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { private func collectStaticMembers(in members: MemberBlockItemListSyntax, typeName: String) { for member in members { if let function = member.decl.as(FunctionDeclSyntax.self) { - if AttributeChecker.hasJSFunctionAttribute(function.attributes), - let parsed = parseFunction(function, enclosingTypeName: typeName, isStaticMember: true) + if let jsFunction = AttributeChecker.firstJSFunctionAttribute(function.attributes), + let parsed = parseFunction(jsFunction, function, enclosingTypeName: typeName, isStaticMember: true) { importedFunctions.append(parsed) } else if AttributeChecker.hasJSSetterAttribute(function.attributes) { @@ -2173,6 +2359,7 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { } private func parseFunction( + _ jsFunction: AttributeSyntax, _ node: FunctionDeclSyntax, enclosingTypeName: String?, isStaticMember: Bool @@ -2183,6 +2370,8 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { } let baseName = SwiftToSkeleton.normalizeIdentifier(node.name.text) + let jsName = AttributeChecker.extractJSName(from: jsFunction) + let from = AttributeChecker.extractJSImportFrom(from: jsFunction) let name: String if isStaticMember, let enclosingTypeName { name = "\(enclosingTypeName)_\(baseName)" @@ -2202,6 +2391,8 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { } return ImportedFunctionSkeleton( name: name, + jsName: jsName, + from: from, parameters: parameters, returnType: returnType, documentation: nil @@ -2223,7 +2414,10 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { return (identifier, typeAnnotation.type) } - private func parseGetterSkeleton(_ node: VariableDeclSyntax) -> ImportedGetterSkeleton? { + private func parseGetterSkeleton( + _ jsGetter: AttributeSyntax, + _ node: VariableDeclSyntax + ) -> ImportedGetterSkeleton? { guard let (identifier, type) = extractPropertyInfo(node) else { return nil } @@ -2231,8 +2425,12 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { return nil } let propertyName = SwiftToSkeleton.normalizeIdentifier(identifier.identifier.text) + let jsName = AttributeChecker.extractJSName(from: jsGetter) + let from = AttributeChecker.extractJSImportFrom(from: jsGetter) return ImportedGetterSkeleton( name: propertyName, + jsName: jsName, + from: from, type: propertyType, documentation: nil, functionName: nil @@ -2252,7 +2450,6 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { guard let (propertyName, functionBaseName) = PropertyNameResolver.resolve( functionName: functionName, - jsName: validation.jsName, normalizeIdentifier: SwiftToSkeleton.normalizeIdentifier ) else { @@ -2261,6 +2458,7 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { return ImportedSetterSkeleton( name: propertyName, + jsName: validation.jsName, type: validation.valueType, documentation: nil, functionName: "\(functionBaseName)_set" diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index 929e6e4cd..60b55cd47 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -80,6 +80,7 @@ public struct BridgeJSLink { var topLevelDtsTypeLines: [String] = [] var importObjectBuilders: [ImportObjectBuilder] = [] var enumStaticAssignments: [String] = [] + var needsImportsObject: Bool = false } private func collectLinkData() throws -> LinkData { @@ -173,12 +174,21 @@ public struct BridgeJSLink { let importObjectBuilder = ImportObjectBuilder(moduleName: unified.moduleName) for fileSkeleton in imported.children { for getter in fileSkeleton.globalGetters { + if getter.from == nil { + data.needsImportsObject = true + } try renderImportedGlobalGetter(importObjectBuilder: importObjectBuilder, getter: getter) } for function in fileSkeleton.functions { + if function.from == nil { + data.needsImportsObject = true + } try renderImportedFunction(importObjectBuilder: importObjectBuilder, function: function) } for type in fileSkeleton.types { + if type.constructor != nil, type.from == nil { + data.needsImportsObject = true + } try renderImportedType(importObjectBuilder: importObjectBuilder, type: type) } } @@ -245,6 +255,7 @@ public struct BridgeJSLink { "let \(JSGlueVariableScope.reservedTmpParamF64s) = [];", "let \(JSGlueVariableScope.reservedTmpRetPointers) = [];", "let \(JSGlueVariableScope.reservedTmpParamPointers) = [];", + "let \(JSGlueVariableScope.reservedTmpStructCleanups) = [];", "const \(JSGlueVariableScope.reservedEnumHelpers) = {};", "const \(JSGlueVariableScope.reservedStructHelpers) = {};", "", @@ -293,8 +304,9 @@ public struct BridgeJSLink { } } - private func generateAddImports() -> CodeFragmentPrinter { + private func generateAddImports(needsImportsObject: Bool) -> CodeFragmentPrinter { let printer = CodeFragmentPrinter() + let allStructs = skeletons.compactMap { $0.exported?.structs }.flatMap { $0 } printer.write("return {") printer.indent { printer.write(lines: [ @@ -309,7 +321,7 @@ public struct BridgeJSLink { "bjs = {};", "importObject[\"bjs\"] = bjs;", ]) - if skeletons.contains(where: { $0.imported != nil }) { + if needsImportsObject { printer.write(lines: [ "const imports = options.getImports(importsContext);" ]) @@ -378,7 +390,7 @@ public struct BridgeJSLink { printer.write("\(JSGlueVariableScope.reservedTmpRetTag) = tag;") } printer.write("}") - printer.write("bjs[\"swift_js_push_int\"] = function(v) {") + printer.write("bjs[\"swift_js_push_i32\"] = function(v) {") printer.indent { printer.write("\(JSGlueVariableScope.reservedTmpRetInts).push(v | 0);") } @@ -402,17 +414,17 @@ public struct BridgeJSLink { printer.write("\(JSGlueVariableScope.reservedTmpRetStrings).push(value);") } printer.write("}") - printer.write("bjs[\"swift_js_pop_param_int32\"] = function() {") + printer.write("bjs[\"swift_js_pop_i32\"] = function() {") printer.indent { printer.write("return \(JSGlueVariableScope.reservedTmpParamInts).pop();") } printer.write("}") - printer.write("bjs[\"swift_js_pop_param_f32\"] = function() {") + printer.write("bjs[\"swift_js_pop_f32\"] = function() {") printer.indent { printer.write("return \(JSGlueVariableScope.reservedTmpParamF32s).pop();") } printer.write("}") - printer.write("bjs[\"swift_js_pop_param_f64\"] = function() {") + printer.write("bjs[\"swift_js_pop_f64\"] = function() {") printer.indent { printer.write("return \(JSGlueVariableScope.reservedTmpParamF64s).pop();") } @@ -422,11 +434,57 @@ public struct BridgeJSLink { printer.write("\(JSGlueVariableScope.reservedTmpRetPointers).push(pointer);") } printer.write("}") - printer.write("bjs[\"swift_js_pop_param_pointer\"] = function() {") + printer.write("bjs[\"swift_js_pop_pointer\"] = function() {") printer.indent { printer.write("return \(JSGlueVariableScope.reservedTmpParamPointers).pop();") } printer.write("}") + printer.write("bjs[\"swift_js_struct_cleanup\"] = function(cleanupId) {") + printer.indent { + printer.write("if (cleanupId === 0) { return; }") + printer.write("const index = (cleanupId | 0) - 1;") + printer.write("const cleanup = \(JSGlueVariableScope.reservedTmpStructCleanups)[index];") + printer.write("\(JSGlueVariableScope.reservedTmpStructCleanups)[index] = null;") + printer.write("if (cleanup) { cleanup(); }") + printer.write( + "while (\(JSGlueVariableScope.reservedTmpStructCleanups).length > 0 && \(JSGlueVariableScope.reservedTmpStructCleanups)[\(JSGlueVariableScope.reservedTmpStructCleanups).length - 1] == null) {" + ) + printer.indent { + printer.write("\(JSGlueVariableScope.reservedTmpStructCleanups).pop();") + } + printer.write("}") + } + printer.write("}") + + if !allStructs.isEmpty { + for structDef in allStructs { + printer.write("bjs[\"swift_js_struct_lower_\(structDef.name)\"] = function(objectId) {") + printer.indent { + printer.write( + "const { cleanup: cleanup } = \(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lower(\(JSGlueVariableScope.reservedSwift).memory.getObject(objectId));" + ) + printer.write("if (cleanup) {") + printer.indent { + printer.write( + "return \(JSGlueVariableScope.reservedTmpStructCleanups).push(cleanup);" + ) + } + printer.write("}") + printer.write("return 0;") + } + printer.write("}") + + printer.write("bjs[\"swift_js_struct_lift_\(structDef.name)\"] = function() {") + printer.indent { + printer.write( + "const value = \(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lift(\(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s), \(JSGlueVariableScope.reservedTmpRetPointers));" + ) + printer.write("return \(JSGlueVariableScope.reservedSwift).memory.retain(value);") + } + printer.write("}") + } + } + printer.write("bjs[\"swift_js_return_optional_bool\"] = function(isSome, value) {") printer.indent { printer.write("if (isSome === 0) {") @@ -994,7 +1052,7 @@ public struct BridgeJSLink { printer.write(lines: structPrinter.lines) } printer.nextLine() - printer.write(contentsOf: generateAddImports()) + printer.write(contentsOf: generateAddImports(needsImportsObject: data.needsImportsObject)) } printer.indent() @@ -1194,25 +1252,29 @@ public struct BridgeJSLink { // Add methods for method in type.methods { + let methodName = method.jsName ?? method.name let methodSignature = - "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: Effects(isAsync: false, isThrows: false)));" + "\(renderTSPropertyName(methodName))\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: Effects(isAsync: false, isThrows: false)));" printer.write(methodSignature) } // Add properties from getters var propertyNames = Set() for getter in type.getters { - propertyNames.insert(getter.name) - let hasSetter = type.setters.contains { $0.name == getter.name } + let propertyName = getter.jsName ?? getter.name + propertyNames.insert(propertyName) + let hasSetter = type.setters.contains { ($0.jsName ?? $0.name) == propertyName } let propertySignature = hasSetter - ? "\(getter.name): \(resolveTypeScriptType(getter.type));" - : "readonly \(getter.name): \(resolveTypeScriptType(getter.type));" + ? "\(renderTSPropertyName(propertyName)): \(resolveTypeScriptType(getter.type));" + : "readonly \(renderTSPropertyName(propertyName)): \(resolveTypeScriptType(getter.type));" printer.write(propertySignature) } // Add setters that don't have corresponding getters - for setter in type.setters where !propertyNames.contains(setter.name) { - printer.write("\(setter.name): \(resolveTypeScriptType(setter.type));") + for setter in type.setters { + let propertyName = setter.jsName ?? setter.name + guard !propertyNames.contains(propertyName) else { continue } + printer.write("\(renderTSPropertyName(propertyName)): \(resolveTypeScriptType(setter.type));") } printer.unindent() @@ -1368,6 +1430,14 @@ public struct BridgeJSLink { return name.components(separatedBy: ".").last ?? name case .optional(let wrapped): return "\(resolveTypeScriptType(wrapped, exportedSkeletons: exportedSkeletons)) | null" + case .array(let elementType): + let elementTypeStr = resolveTypeScriptType(elementType, exportedSkeletons: exportedSkeletons) + // Parenthesize compound types so `[]` binds correctly in TypeScript + // e.g. `(string | null)[]` not `string | null[]`, `((x: number) => void)[]` not `(x: number) => void[]` + if elementTypeStr.contains("|") || elementTypeStr.contains("=>") { + return "(\(elementTypeStr))[]" + } + return "\(elementTypeStr)[]" default: return type.tsType } @@ -1387,6 +1457,20 @@ public struct BridgeJSLink { return "(\(parameterSignatures.joined(separator: ", "))): \(returnTypeWithEffect)" } + private func renderTSPropertyName(_ name: String) -> String { + // TypeScript allows quoted property names for keys that aren't valid identifiers. + if name.range(of: #"^[$A-Z_][0-9A-Z_$]*$"#, options: [.regularExpression, .caseInsensitive]) != nil { + return name + } + return "\"\(Self.escapeForJavaScriptStringLiteral(name))\"" + } + + fileprivate static func escapeForJavaScriptStringLiteral(_ string: String) -> String { + string + .replacingOccurrences(of: "\\", with: "\\\\") + .replacingOccurrences(of: "\"", with: "\\\"") + } + /// Helper method to append JSDoc comments for parameters with default values private func appendJSDocIfNeeded(for parameters: [Parameter], to lines: inout [String]) { let jsDocLines = DefaultValueUtils.formatJSDoc(for: parameters) @@ -2109,8 +2193,13 @@ extension BridgeJSLink { return printer.lines } + func call(name: String, fromObjectExpr: String, returnType: BridgeType) throws -> String? { + let calleeExpr = Self.propertyAccessExpr(objectExpr: fromObjectExpr, propertyName: name) + return try self.call(calleeExpr: calleeExpr, returnType: returnType) + } + func call(name: String, returnType: BridgeType) throws -> String? { - return try self.call(calleeExpr: "imports.\(name)", returnType: returnType) + return try call(name: name, fromObjectExpr: "imports", returnType: returnType) } private func call(calleeExpr: String, returnType: BridgeType) throws -> String? { @@ -2136,21 +2225,30 @@ extension BridgeJSLink { ) } - func callConstructor(name: String) throws -> String? { - let call = "new imports.\(name)(\(parameterForwardings.joined(separator: ", ")))" - let type: BridgeType = .jsObject(name) + func callConstructor(jsName: String, swiftTypeName: String, fromObjectExpr: String) throws -> String? { + let ctorExpr = Self.propertyAccessExpr(objectExpr: fromObjectExpr, propertyName: jsName) + let call = "new \(ctorExpr)(\(parameterForwardings.joined(separator: ", ")))" + let type: BridgeType = .jsObject(swiftTypeName) let loweringFragment = try IntrinsicJSFragment.lowerReturn(type: type, context: context) return try lowerReturnValue(returnType: type, returnExpr: call, loweringFragment: loweringFragment) } + func callConstructor(jsName: String, swiftTypeName: String) throws -> String? { + return try callConstructor(jsName: jsName, swiftTypeName: swiftTypeName, fromObjectExpr: "imports") + } + func callMethod(name: String, returnType: BridgeType) throws -> String? { + let objectExpr = "\(JSGlueVariableScope.reservedSwift).memory.getObject(self)" + let calleeExpr = Self.propertyAccessExpr(objectExpr: objectExpr, propertyName: name) return try call( - calleeExpr: "\(JSGlueVariableScope.reservedSwift).memory.getObject(self).\(name)", + calleeExpr: calleeExpr, returnType: returnType ) } func callPropertyGetter(name: String, returnType: BridgeType) throws -> String? { + let objectExpr = "\(JSGlueVariableScope.reservedSwift).memory.getObject(self)" + let accessExpr = Self.propertyAccessExpr(objectExpr: objectExpr, propertyName: name) if context == .exportSwift, returnType.usesSideChannelForOptionalReturn() { guard case .optional(let wrappedType) = returnType else { fatalError("usesSideChannelForOptionalReturn returned true for non-optional type") @@ -2158,7 +2256,7 @@ extension BridgeJSLink { let resultVar = scope.variable("ret") body.write( - "let \(resultVar) = \(JSGlueVariableScope.reservedSwift).memory.getObject(self).\(name);" + "let \(resultVar) = \(accessExpr);" ) let fragment = try IntrinsicJSFragment.protocolPropertyOptionalToSideChannel(wrappedType: wrappedType) @@ -2168,24 +2266,25 @@ extension BridgeJSLink { } return try call( - callExpr: "\(JSGlueVariableScope.reservedSwift).memory.getObject(self).\(name)", + callExpr: accessExpr, returnType: returnType ) } func callPropertySetter(name: String, returnType: BridgeType) { - let call = - "\(JSGlueVariableScope.reservedSwift).memory.getObject(self).\(name) = \(parameterForwardings.joined(separator: ", "))" + let objectExpr = "\(JSGlueVariableScope.reservedSwift).memory.getObject(self)" + let accessExpr = Self.propertyAccessExpr(objectExpr: objectExpr, propertyName: name) + let call = "\(accessExpr) = \(parameterForwardings.joined(separator: ", "))" body.write("\(call);") } - func getImportProperty(name: String, returnType: BridgeType) throws -> String? { + func getImportProperty(name: String, fromObjectExpr: String, returnType: BridgeType) throws -> String? { if returnType == .void { throw BridgeJSLinkError(message: "Void is not supported for imported JS properties") } let loweringFragment = try IntrinsicJSFragment.lowerReturn(type: returnType, context: context) - let expr = "imports[\"\(name)\"]" + let expr = Self.propertyAccessExpr(objectExpr: fromObjectExpr, propertyName: name) let returnExpr: String? if loweringFragment.parameters.count == 0 { @@ -2204,6 +2303,10 @@ extension BridgeJSLink { ) } + func getImportProperty(name: String, returnType: BridgeType) throws -> String? { + return try getImportProperty(name: name, fromObjectExpr: "imports", returnType: returnType) + } + private func lowerReturnValue( returnType: BridgeType, returnExpr: String?, @@ -2214,6 +2317,15 @@ extension BridgeJSLink { assert(loweredValues.count <= 1, "Lowering fragment should produce at most one value") return loweredValues.first } + + private static func propertyAccessExpr(objectExpr: String, propertyName: String) -> String { + if propertyName.range(of: #"^[$A-Z_][0-9A-Z_$]*$"#, options: [.regularExpression, .caseInsensitive]) != nil + { + return "\(objectExpr).\(propertyName)" + } + let escapedName = BridgeJSLink.escapeForJavaScriptStringLiteral(propertyName) + return "\(objectExpr)[\"\(escapedName)\"]" + } } class ImportObjectBuilder { @@ -2928,18 +3040,26 @@ extension BridgeJSLink { for param in function.parameters { try thunkBuilder.liftParameter(param: param) } - let returnExpr = try thunkBuilder.call(name: function.name, returnType: function.returnType) + let jsName = function.jsName ?? function.name + let importRootExpr = function.from == .global ? "globalThis" : "imports" + let returnExpr = try thunkBuilder.call( + name: jsName, + fromObjectExpr: importRootExpr, + returnType: function.returnType + ) let funcLines = thunkBuilder.renderFunction( name: function.abiName(context: nil), returnExpr: returnExpr, returnType: function.returnType ) let effects = Effects(isAsync: false, isThrows: false) - importObjectBuilder.appendDts( - [ - "\(function.name)\(renderTSSignature(parameters: function.parameters, returnType: function.returnType, effects: effects));" - ] - ) + if function.from == nil { + importObjectBuilder.appendDts( + [ + "\(renderTSPropertyName(jsName))\(renderTSSignature(parameters: function.parameters, returnType: function.returnType, effects: effects));" + ] + ) + } importObjectBuilder.assignToImportObject(name: function.abiName(context: nil), function: funcLines) } @@ -2948,14 +3068,22 @@ extension BridgeJSLink { getter: ImportedGetterSkeleton ) throws { let thunkBuilder = ImportedThunkBuilder() - let returnExpr = try thunkBuilder.getImportProperty(name: getter.name, returnType: getter.type) + let jsName = getter.jsName ?? getter.name + let importRootExpr = getter.from == .global ? "globalThis" : "imports" + let returnExpr = try thunkBuilder.getImportProperty( + name: jsName, + fromObjectExpr: importRootExpr, + returnType: getter.type + ) let abiName = getter.abiName(context: nil) let funcLines = thunkBuilder.renderFunction( name: abiName, returnExpr: returnExpr, returnType: getter.type ) - importObjectBuilder.appendDts(["readonly \(getter.name): \(getter.type.tsType);"]) + if getter.from == nil { + importObjectBuilder.appendDts(["readonly \(renderTSPropertyName(jsName)): \(getter.type.tsType);"]) + } importObjectBuilder.assignToImportObject(name: abiName, function: funcLines) } @@ -2976,7 +3104,10 @@ extension BridgeJSLink { getter: getter, abiName: getterAbiName, emitCall: { thunkBuilder in - return try thunkBuilder.callPropertyGetter(name: getter.name, returnType: getter.type) + return try thunkBuilder.callPropertyGetter( + name: getter.jsName ?? getter.name, + returnType: getter.type + ) } ) importObjectBuilder.assignToImportObject(name: getterAbiName, function: js) @@ -2992,7 +3123,7 @@ extension BridgeJSLink { try thunkBuilder.liftParameter( param: Parameter(label: nil, name: "newValue", type: setter.type) ) - thunkBuilder.callPropertySetter(name: setter.name, returnType: setter.type) + thunkBuilder.callPropertySetter(name: setter.jsName ?? setter.name, returnType: setter.type) return nil } ) @@ -3016,7 +3147,12 @@ extension BridgeJSLink { try thunkBuilder.liftParameter(param: param) } let returnType = BridgeType.jsObject(type.name) - let returnExpr = try thunkBuilder.callConstructor(name: type.name) + let importRootExpr = type.from == .global ? "globalThis" : "imports" + let returnExpr = try thunkBuilder.callConstructor( + jsName: type.jsName ?? type.name, + swiftTypeName: type.name, + fromObjectExpr: importRootExpr + ) let abiName = constructor.abiName(context: type) let funcLines = thunkBuilder.renderFunction( name: abiName, @@ -3025,16 +3161,18 @@ extension BridgeJSLink { ) importObjectBuilder.assignToImportObject(name: abiName, function: funcLines) - let dtsPrinter = CodeFragmentPrinter() - dtsPrinter.write("\(type.name): {") - dtsPrinter.indent { - dtsPrinter.write( - "new\(renderTSSignature(parameters: constructor.parameters, returnType: returnType, effects: Effects(isAsync: false, isThrows: false)));" - ) - } - dtsPrinter.write("}") + if type.from == nil { + let dtsPrinter = CodeFragmentPrinter() + dtsPrinter.write("\(type.name): {") + dtsPrinter.indent { + dtsPrinter.write( + "new\(renderTSSignature(parameters: constructor.parameters, returnType: returnType, effects: Effects(isAsync: false, isThrows: false)));" + ) + } + dtsPrinter.write("}") - importObjectBuilder.appendDts(dtsPrinter.lines) + importObjectBuilder.appendDts(dtsPrinter.lines) + } } func renderImportedGetter( @@ -3078,7 +3216,7 @@ extension BridgeJSLink { for param in method.parameters { try thunkBuilder.liftParameter(param: param) } - let returnExpr = try thunkBuilder.callMethod(name: method.name, returnType: method.returnType) + let returnExpr = try thunkBuilder.callMethod(name: method.jsName ?? method.name, returnType: method.returnType) let funcLines = thunkBuilder.renderFunction( name: method.abiName(context: context), returnExpr: returnExpr, @@ -3195,6 +3333,11 @@ enum DefaultValueUtils { "\(field.name): \(Self.format(field.value, as: format))" } return "{ \(fieldStrings.joined(separator: ", ")) }" + case .array(let elements): + let elementStrings = elements.map { element in + DefaultValueUtils.format(element, as: format) + } + return "[\(elementStrings.joined(separator: ", "))]" } } @@ -3246,7 +3389,7 @@ extension BridgeType { return "void" case .string: return "string" - case .int: + case .int, .uint: return "number" case .float: return "number" @@ -3258,6 +3401,8 @@ extension BridgeType { return name ?? "any" case .swiftHeapObject(let name): return name + case .unsafePointer: + return "number" case .optional(let wrappedType): return "\(wrappedType.tsType) | null" case .caseEnum(let name): @@ -3277,6 +3422,12 @@ extension BridgeType { "arg\(index): \(param.tsType)" }.joined(separator: ", ") return "(\(paramTypes)) => \(signature.returnType.tsType)" + case .array(let elementType): + let inner = elementType.tsType + if inner.contains("|") || inner.contains("=>") { + return "(\(inner))[]" + } + return "\(inner)[]" } } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index d9223faf8..28f756a43 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -30,6 +30,7 @@ final class JSGlueVariableScope { static let reservedTmpParamF64s = "tmpParamF64s" static let reservedTmpRetPointers = "tmpRetPointers" static let reservedTmpParamPointers = "tmpParamPointers" + static let reservedTmpStructCleanups = "tmpStructCleanups" static let reservedEnumHelpers = "enumHelpers" static let reservedStructHelpers = "structHelpers" @@ -58,6 +59,7 @@ final class JSGlueVariableScope { reservedTmpParamF64s, reservedTmpRetPointers, reservedTmpParamPointers, + reservedTmpStructCleanups, reservedEnumHelpers, reservedStructHelpers, ] @@ -143,6 +145,15 @@ struct IntrinsicJSFragment: Sendable { } ) + /// Convert signed Int32 to unsigned for UInt values + static let uintLiftReturn = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanupCode in + return ["\(arguments[0]) >>> 0"] + } + ) + static let uintLiftParameter = uintLiftReturn + static let stringLowerParameter = IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, scope, printer, cleanupCode in @@ -202,6 +213,18 @@ struct IntrinsicJSFragment: Sendable { return [resultLabel] } ) + static let jsObjectLiftRetainedObjectId = IntrinsicJSFragment( + parameters: ["objectId"], + printCode: { arguments, scope, printer, cleanupCode in + let resultLabel = scope.variable("value") + let objectId = arguments[0] + printer.write( + "const \(resultLabel) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(objectId));" + ) + printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(objectId));") + return [resultLabel] + } + ) static let jsObjectLiftParameter = IntrinsicJSFragment( parameters: ["objectId"], printCode: { arguments, scope, printer, cleanupCode in @@ -266,7 +289,7 @@ struct IntrinsicJSFragment: Sendable { printCode: { _, scope, printer, _ in let retName = scope.variable("ret") printer.write( - "const \(retName) = \(JSGlueVariableScope.reservedEnumHelpers).\(enumBase).raise(\(JSGlueVariableScope.reservedTmpRetTag), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" + "const \(retName) = \(JSGlueVariableScope.reservedEnumHelpers).\(enumBase).lift(\(JSGlueVariableScope.reservedTmpRetTag), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" ) return [retName] } @@ -329,7 +352,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("if (\(isSome)) {") printer.indent { printer.write( - "\(enumVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).raise(\(wrappedValue), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" + "\(enumVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(wrappedValue), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" ) } printer.write("}") @@ -341,7 +364,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("if (\(isSome)) {") printer.indent { printer.write( - "\(structVar) = \(JSGlueVariableScope.reservedStructHelpers).\(base).raise(\(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s), \(JSGlueVariableScope.reservedTmpRetPointers));" + "\(structVar) = \(JSGlueVariableScope.reservedStructHelpers).\(base).lift(\(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s), \(JSGlueVariableScope.reservedTmpRetPointers));" ) } printer.write("} else {") @@ -350,6 +373,24 @@ struct IntrinsicJSFragment: Sendable { } printer.write("}") resultExpr = structVar + case .array(let elementType): + let arrayVar = scope.variable("arrayValue") + printer.write("let \(arrayVar);") + printer.write("if (\(isSome)) {") + printer.indent { + // Lift array from stacks - reuse array lift return logic + let arrayLiftFragment = try! arrayLift(elementType: elementType) + let liftResults = arrayLiftFragment.printCode([], scope, printer, cleanupCode) + if let liftResult = liftResults.first { + printer.write("\(arrayVar) = \(liftResult);") + } + } + printer.write("} else {") + printer.indent { + printer.write("\(arrayVar) = null;") + } + printer.write("}") + resultExpr = arrayVar default: resultExpr = "\(isSome) ? \(wrappedValue) : null" } @@ -423,6 +464,23 @@ struct IntrinsicJSFragment: Sendable { case .rawValueEnum: // Raw value enums with optional - falls through to handle based on raw type return ["+\(isSomeVar)", "\(isSomeVar) ? \(value) : 0"] + case .array(let elementType): + let cleanupArrayVar = scope.variable("\(value)Cleanups") + printer.write("const \(cleanupArrayVar) = [];") + printer.write("if (\(isSomeVar)) {") + printer.indent { + let arrayLowerFragment = try! arrayLower(elementType: elementType) + let arrayCleanup = CodeFragmentPrinter() + let _ = arrayLowerFragment.printCode([value], scope, printer, arrayCleanup) + if !arrayCleanup.lines.isEmpty { + for line in arrayCleanup.lines { + printer.write("\(cleanupArrayVar).push(() => { \(line) });") + } + } + } + printer.write("}") + cleanupCode.write("for (const cleanup of \(cleanupArrayVar)) { cleanup(); }") + return ["+\(isSomeVar)"] default: switch wrappedType { case .swiftHeapObject: @@ -466,7 +524,7 @@ struct IntrinsicJSFragment: Sendable { case .bool: printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalBool);") printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalBool) = undefined;") - case .int: + case .int, .uint: printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalInt);") printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = undefined;") case .float: @@ -533,7 +591,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("} else {") printer.indent { printer.write( - "\(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).raise(\(JSGlueVariableScope.reservedTmpRetTag), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" + "\(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(JSGlueVariableScope.reservedTmpRetTag), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" ) } printer.write("}") @@ -545,7 +603,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("if (\(isSomeVar)) {") printer.indent { printer.write( - "\(resultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(base).raise(\(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s), \(JSGlueVariableScope.reservedTmpRetPointers));" + "\(resultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(base).lift(\(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s), \(JSGlueVariableScope.reservedTmpRetPointers));" ) } printer.write("} else {") @@ -553,6 +611,23 @@ struct IntrinsicJSFragment: Sendable { printer.write("\(resultVar) = null;") } printer.write("}") + case .array(let elementType): + let isSomeVar = scope.variable("isSome") + printer.write("const \(isSomeVar) = \(JSGlueVariableScope.reservedTmpRetInts).pop();") + printer.write("let \(resultVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + let arrayLiftFragment = try! arrayLift(elementType: elementType) + let liftResults = arrayLiftFragment.printCode([], scope, printer, cleanupCode) + if let liftResult = liftResults.first { + printer.write("\(resultVar) = \(liftResult);") + } + } + printer.write("} else {") + printer.indent { + printer.write("\(resultVar) = null;") + } + printer.write("}") default: printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnString);") printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") @@ -581,7 +656,7 @@ struct IntrinsicJSFragment: Sendable { printer.write( "bjs[\"swift_js_return_optional_bool\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? (\(value) ? 1 : 0) : 0);" ) - case .int: + case .int, .uint: printer.write( "bjs[\"swift_js_return_optional_int\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? (\(value) | 0) : 0);" ) @@ -825,7 +900,7 @@ struct IntrinsicJSFragment: Sendable { let targetVar = arguments[1] let base = fullName.components(separatedBy: ".").last ?? fullName printer.write( - "let \(targetVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).raise(\(caseId), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" + "let \(targetVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(caseId), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" ) return [] } @@ -867,7 +942,7 @@ struct IntrinsicJSFragment: Sendable { ) printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(value));") printer.write("\(targetVar) = String(\(objectLabel));") - case .int: + case .int, .uint: printer.write("\(targetVar) = \(value) | 0;") case .bool: printer.write("\(targetVar) = \(value) !== 0;") @@ -892,7 +967,7 @@ struct IntrinsicJSFragment: Sendable { case .associatedValueEnum(let fullName): let base = fullName.components(separatedBy: ".").last ?? fullName printer.write( - "\(targetVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).raise(\(value), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" + "\(targetVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(value), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" ) default: fatalError("Unsupported optional wrapped type in closure parameter lifting: \(wrappedType)") @@ -1051,7 +1126,7 @@ struct IntrinsicJSFragment: Sendable { case .string: printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = \(result);") printer.write("return;") - case .int: + case .int, .uint: printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = \(result);") printer.write("return;") case .bool: @@ -1220,7 +1295,7 @@ struct IntrinsicJSFragment: Sendable { let base = fullName.components(separatedBy: ".").last ?? fullName let resultVar = scope.variable("result") printer.write( - "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).raise(\(JSGlueVariableScope.reservedTmpRetTag), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" + "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(JSGlueVariableScope.reservedTmpRetTag), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" ) printer.write("return \(resultVar);") return [] @@ -1300,7 +1375,7 @@ struct IntrinsicJSFragment: Sendable { /// Returns a fragment that lowers a JS value to Wasm core values for parameters static func lowerParameter(type: BridgeType) throws -> IntrinsicJSFragment { switch type { - case .int, .float, .double, .bool: return .identity + case .int, .uint, .float, .double, .bool, .unsafePointer: return .identity case .string: return .stringLowerParameter case .jsObject: return .jsObjectLowerParameter case .swiftHeapObject: @@ -1335,6 +1410,8 @@ struct IntrinsicJSFragment: Sendable { ) case .namespaceEnum(let string): throw BridgeJSLinkError(message: "Namespace enums are not supported to be passed as parameters: \(string)") + case .array(let elementType): + return try arrayLower(elementType: elementType) } } @@ -1342,10 +1419,12 @@ struct IntrinsicJSFragment: Sendable { static func liftReturn(type: BridgeType) throws -> IntrinsicJSFragment { switch type { case .int, .float, .double: return .identity + case .uint: return .uintLiftReturn case .bool: return .boolLiftReturn case .string: return .stringLiftReturn case .jsObject: return .jsObjectLiftReturn case .swiftHeapObject(let name): return .swiftHeapObjectLiftReturn(name) + case .unsafePointer: return .identity case .swiftProtocol: return .jsObjectLiftReturn case .void: return .void case .optional(let wrappedType): return .optionalLiftReturn(wrappedType: wrappedType) @@ -1376,6 +1455,8 @@ struct IntrinsicJSFragment: Sendable { throw BridgeJSLinkError( message: "Namespace enums are not supported to be returned from functions: \(string)" ) + case .array(let elementType): + return try arrayLift(elementType: elementType) } } @@ -1385,9 +1466,11 @@ struct IntrinsicJSFragment: Sendable { static func liftParameter(type: BridgeType, context: BridgeContext = .importTS) throws -> IntrinsicJSFragment { switch type { case .int, .float, .double: return .identity + case .uint: return .uintLiftParameter case .bool: return .boolLiftParameter case .string: return .stringLiftParameter case .jsObject: return .jsObjectLiftParameter + case .unsafePointer: return .identity case .swiftHeapObject(let name): switch context { case .importTS: @@ -1433,7 +1516,7 @@ struct IntrinsicJSFragment: Sendable { let caseId = arguments[0] let resultVar = scope.variable("enumValue") printer.write( - "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).raise(\(caseId), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" + "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(caseId), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" ) return [resultVar] } @@ -1442,10 +1525,7 @@ struct IntrinsicJSFragment: Sendable { case .swiftStruct(let fullName): switch context { case .importTS: - throw BridgeJSLinkError( - message: - "Swift structs are not supported to be passed as parameters to imported JS functions: \(fullName)" - ) + return .jsObjectLiftRetainedObjectId case .exportSwift: let base = fullName.components(separatedBy: ".").last ?? fullName return IntrinsicJSFragment( @@ -1453,7 +1533,7 @@ struct IntrinsicJSFragment: Sendable { printCode: { arguments, scope, printer, cleanupCode in let resultVar = scope.variable("structValue") printer.write( - "const \(resultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(base).raise(\(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s), \(JSGlueVariableScope.reservedTmpRetPointers));" + "const \(resultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(base).lift(\(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s), \(JSGlueVariableScope.reservedTmpRetPointers));" ) return [resultVar] } @@ -1472,16 +1552,26 @@ struct IntrinsicJSFragment: Sendable { message: "Namespace enums are not supported to be passed as parameters to imported JS functions: \(string)" ) + case .array(let elementType): + switch context { + case .importTS: + throw BridgeJSLinkError( + message: "Arrays are not yet supported to be passed as parameters to imported JS functions" + ) + case .exportSwift: + return try arrayLift(elementType: elementType) + } } } /// Returns a fragment that lowers a JS value to Wasm core values for return values static func lowerReturn(type: BridgeType, context: BridgeContext = .importTS) throws -> IntrinsicJSFragment { switch type { - case .int, .float, .double: return .identity + case .int, .uint, .float, .double: return .identity case .bool: return .boolLowerReturn case .string: return .stringLowerReturn case .jsObject: return .jsObjectLowerReturn + case .unsafePointer: return .identity case .swiftHeapObject(let name): switch context { case .importTS: @@ -1522,10 +1612,8 @@ struct IntrinsicJSFragment: Sendable { case .swiftStruct(let fullName): switch context { case .importTS: - throw BridgeJSLinkError( - message: - "Swift structs are not supported to be returned from imported JS functions: \(fullName)" - ) + // ImportTS expects Swift structs to come back as a retained JS object ID. + return .jsObjectLowerReturn case .exportSwift: return swiftStructLowerReturn(fullName: fullName) } @@ -1546,6 +1634,15 @@ struct IntrinsicJSFragment: Sendable { throw BridgeJSLinkError( message: "Namespace enums are not supported to be returned from imported JS functions: \(string)" ) + case .array(let elementType): + switch context { + case .importTS: + throw BridgeJSLinkError( + message: "Arrays are not yet supported to be returned from imported JS functions" + ) + case .exportSwift: + return try arrayLower(elementType: elementType) + } } } @@ -1624,25 +1721,25 @@ struct IntrinsicJSFragment: Sendable { } printer.write("},") - // Generate raise function + // Generate lift function printer.write( - "raise: (\(JSGlueVariableScope.reservedTmpRetTag), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s)) => {" + "lift: (\(JSGlueVariableScope.reservedTmpRetTag), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s)) => {" ) printer.indent { printer.write("const tag = tmpRetTag | 0;") printer.write("switch (tag) {") printer.indent { - let raisePrinter = CodeFragmentPrinter() + let liftPrinter = CodeFragmentPrinter() for enumCase in enumDefinition.cases { let caseName = enumCase.name.capitalizedFirstLetter let caseScope = JSGlueVariableScope() let caseCleanup = CodeFragmentPrinter() let fragment = IntrinsicJSFragment.associatedValuePopPayload(enumCase: enumCase) - _ = fragment.printCode([enumName, caseName], caseScope, raisePrinter, caseCleanup) + _ = fragment.printCode([enumName, caseName], caseScope, liftPrinter, caseCleanup) } - for line in raisePrinter.lines { + for line in liftPrinter.lines { printer.write(line) } @@ -1819,7 +1916,7 @@ struct IntrinsicJSFragment: Sendable { return [] } ) - case .int: + case .int, .uint: return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, scope, printer, cleanup in @@ -1877,7 +1974,7 @@ struct IntrinsicJSFragment: Sendable { cleanup.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(idVar));") } cleanup.write("}") - case .int: + case .int, .uint: printer.write( "\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? (\(value) | 0) : 0);" ) @@ -1934,7 +2031,7 @@ struct IntrinsicJSFragment: Sendable { return [bVar] } ) - case .int: + case .int, .uint: return IntrinsicJSFragment( parameters: [], printCode: { arguments, scope, printer, cleanup in @@ -2036,13 +2133,460 @@ struct IntrinsicJSFragment: Sendable { printCode: { arguments, scope, printer, cleanupCode in let resultVar = scope.variable("structValue") printer.write( - "const \(resultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(structBase).raise(\(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s), \(JSGlueVariableScope.reservedTmpRetPointers));" + "const \(resultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(structBase).lift(\(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s), \(JSGlueVariableScope.reservedTmpRetPointers));" + ) + return [resultVar] + } + ) + } + + // MARK: - Array Helpers + + /// Lowers an array from JS to Swift by iterating elements and pushing to stacks + static func arrayLower(elementType: BridgeType) throws -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["arr"], + printCode: { arguments, scope, printer, cleanupCode in + let arr = arguments[0] + let cleanupArrayVar = scope.variable("arrayCleanups") + + printer.write("const \(cleanupArrayVar) = [];") + let elemVar = scope.variable("elem") + printer.write("for (const \(elemVar) of \(arr)) {") + printer.indent { + let elementFragment = try! arrayElementLowerFragment(elementType: elementType) + let elementCleanup = CodeFragmentPrinter() + let _ = elementFragment.printCode([elemVar], scope, printer, elementCleanup) + if !elementCleanup.lines.isEmpty { + printer.write("\(cleanupArrayVar).push(() => {") + printer.indent { + for line in elementCleanup.lines { + printer.write(line) + } + } + printer.write("});") + } + } + printer.write("}") + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(arr).length);") + cleanupCode.write("for (const cleanup of \(cleanupArrayVar)) { cleanup(); }") + return [] + } + ) + } + + /// Lifts an array from Swift to JS by popping elements from stacks + static func arrayLift(elementType: BridgeType) throws -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanupCode in + let resultVar = scope.variable("arrayResult") + let lenVar = scope.variable("arrayLen") + let iVar = scope.variable("i") + + printer.write("const \(lenVar) = \(JSGlueVariableScope.reservedTmpRetInts).pop();") + printer.write("const \(resultVar) = [];") + printer.write("for (let \(iVar) = 0; \(iVar) < \(lenVar); \(iVar)++) {") + printer.indent { + let elementFragment = try! arrayElementRaiseFragment(elementType: elementType) + let elementResults = elementFragment.printCode([], scope, printer, cleanupCode) + if let elementExpr = elementResults.first { + printer.write("\(resultVar).push(\(elementExpr));") + } + } + printer.write("}") + printer.write("\(resultVar).reverse();") + return [resultVar] + } + ) + } + + private static func arrayElementRaiseFragment(elementType: BridgeType) throws -> IntrinsicJSFragment { + switch elementType { + case .string: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let strVar = scope.variable("string") + printer.write("const \(strVar) = \(JSGlueVariableScope.reservedTmpRetStrings).pop();") + return [strVar] + } + ) + case .bool: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let bVar = scope.variable("bool") + printer.write("const \(bVar) = \(JSGlueVariableScope.reservedTmpRetInts).pop() !== 0;") + return [bVar] + } + ) + case .int, .uint: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let iVar = scope.variable("int") + printer.write("const \(iVar) = \(JSGlueVariableScope.reservedTmpRetInts).pop();") + return [iVar] + } + ) + case .float: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let fVar = scope.variable("f32") + printer.write("const \(fVar) = \(JSGlueVariableScope.reservedTmpRetF32s).pop();") + return [fVar] + } + ) + case .double: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let dVar = scope.variable("f64") + printer.write("const \(dVar) = \(JSGlueVariableScope.reservedTmpRetF64s).pop();") + return [dVar] + } + ) + case .swiftStruct(let fullName): + let structBase = fullName.components(separatedBy: ".").last ?? fullName + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let resultVar = scope.variable("struct") + printer.write( + "const \(resultVar) = structHelpers.\(structBase).lift(\(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s), \(JSGlueVariableScope.reservedTmpRetPointers));" + ) + return [resultVar] + } + ) + case .caseEnum: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let varName = scope.variable("caseId") + printer.write("const \(varName) = \(JSGlueVariableScope.reservedTmpRetInts).pop();") + return [varName] + } + ) + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let varName = scope.variable("rawValue") + printer.write("const \(varName) = \(JSGlueVariableScope.reservedTmpRetStrings).pop();") + return [varName] + } + ) + default: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let varName = scope.variable("rawValue") + printer.write("const \(varName) = \(JSGlueVariableScope.reservedTmpRetInts).pop();") + return [varName] + } + ) + } + case .associatedValueEnum(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let caseIdVar = scope.variable("caseId") + let resultVar = scope.variable("enumValue") + printer.write("const \(caseIdVar) = \(JSGlueVariableScope.reservedTmpRetInts).pop();") + printer.write( + "const \(resultVar) = enumHelpers.\(base).lift(\(caseIdVar), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" + ) + return [resultVar] + } + ) + case .swiftHeapObject(let className): + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let ptrVar = scope.variable("ptr") + let objVar = scope.variable("obj") + printer.write("const \(ptrVar) = \(JSGlueVariableScope.reservedTmpRetPointers).pop();") + printer.write("const \(objVar) = \(className).__construct(\(ptrVar));") + return [objVar] + } + ) + case .jsObject, .swiftProtocol: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let idVar = scope.variable("objId") + let objVar = scope.variable("obj") + printer.write("const \(idVar) = \(JSGlueVariableScope.reservedTmpRetInts).pop();") + printer.write("const \(objVar) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(idVar));") + printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(idVar));") + return [objVar] + } + ) + case .array(let innerElementType): + return try! arrayLift(elementType: innerElementType) + case .optional(let wrappedType): + return try optionalElementRaiseFragment(wrappedType: wrappedType) + case .unsafePointer: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let pVar = scope.variable("pointer") + printer.write("const \(pVar) = \(JSGlueVariableScope.reservedTmpRetPointers).pop();") + return [pVar] + } + ) + case .void, .closure, .namespaceEnum: + throw BridgeJSLinkError(message: "Unsupported array element type: \(elementType)") + } + } + + private static func arrayElementLowerFragment(elementType: BridgeType) throws -> IntrinsicJSFragment { + switch elementType { + case .string: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + let value = arguments[0] + let bytesVar = scope.variable("bytes") + let idVar = scope.variable("id") + printer.write("const \(bytesVar) = textEncoder.encode(\(value));") + printer.write("const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));") + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(bytesVar).length);") + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(idVar));") + cleanup.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(idVar));") + return [] + } + ) + case .bool: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(arguments[0]) ? 1 : 0);") + return [] + } + ) + case .int, .uint: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push((\(arguments[0]) | 0));") + return [] + } + ) + case .float: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + printer.write("\(JSGlueVariableScope.reservedTmpParamF32s).push(Math.fround(\(arguments[0])));") + return [] + } + ) + case .double: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + printer.write("\(JSGlueVariableScope.reservedTmpParamF64s).push(\(arguments[0]));") + return [] + } + ) + case .swiftStruct(let fullName): + let structBase = fullName.components(separatedBy: ".").last ?? fullName + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + let value = arguments[0] + let cleanupVar = scope.variable("cleanup") + printer.write("const { cleanup: \(cleanupVar) } = structHelpers.\(structBase).lower(\(value));") + cleanup.write("if (\(cleanupVar)) { \(cleanupVar)(); }") + return [] + } + ) + case .caseEnum: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push((\(arguments[0]) | 0));") + return [] + } + ) + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + let value = arguments[0] + let bytesVar = scope.variable("bytes") + let idVar = scope.variable("id") + printer.write("const \(bytesVar) = textEncoder.encode(\(value));") + printer.write( + "const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));" + ) + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(bytesVar).length);") + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(idVar));") + cleanup.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(idVar));") + return [] + } + ) + default: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push((\(arguments[0]) | 0));") + return [] + } ) + } + case .associatedValueEnum(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + let value = arguments[0] + let caseIdVar = scope.variable("caseId") + let cleanupVar = scope.variable("enumCleanup") + printer.write( + "const { caseId: \(caseIdVar), cleanup: \(cleanupVar) } = enumHelpers.\(base).lower(\(value));" + ) + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(caseIdVar));") + cleanup.write("if (\(cleanupVar)) { \(cleanupVar)(); }") + return [] + } + ) + case .swiftHeapObject: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + printer.write("\(JSGlueVariableScope.reservedTmpParamPointers).push(\(arguments[0]).pointer);") + return [] + } + ) + case .jsObject: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + let value = arguments[0] + let idVar = scope.variable("objId") + printer.write("const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(idVar));") + cleanup.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(idVar));") + return [] + } + ) + case .array(let innerElementType): + return try! arrayLower(elementType: innerElementType) + case .optional(let wrappedType): + return try optionalElementLowerFragment(wrappedType: wrappedType) + case .swiftProtocol: + // Same as jsObject but no cleanup — Swift's AnyProtocol wrapper releases via deinit + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + let value = arguments[0] + let idVar = scope.variable("objId") + printer.write("const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(idVar));") + return [] + } + ) + case .unsafePointer: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + printer.write("\(JSGlueVariableScope.reservedTmpParamPointers).push((\(arguments[0]) | 0));") + return [] + } + ) + case .void, .closure, .namespaceEnum: + throw BridgeJSLinkError(message: "Unsupported array element type for lowering: \(elementType)") + } + } + + private static func optionalElementRaiseFragment(wrappedType: BridgeType) throws -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let isSomeVar = scope.variable("isSome") + let resultVar = scope.variable("optValue") + + printer.write("const \(isSomeVar) = \(JSGlueVariableScope.reservedTmpRetInts).pop();") + printer.write("let \(resultVar);") + printer.write("if (\(isSomeVar) === 0) {") + printer.indent { + printer.write("\(resultVar) = null;") + } + printer.write("} else {") + printer.indent { + let innerFragment = try! arrayElementRaiseFragment(elementType: wrappedType) + let innerResults = innerFragment.printCode([], scope, printer, cleanup) + if let innerResult = innerResults.first { + printer.write("\(resultVar) = \(innerResult);") + } else { + printer.write("\(resultVar) = undefined;") + } + } + printer.write("}") + return [resultVar] } ) } + private static func optionalElementLowerFragment(wrappedType: BridgeType) throws -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + let value = arguments[0] + let isSomeVar = scope.variable("isSome") + + printer.write("const \(isSomeVar) = \(value) != null ? 1 : 0;") + // 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! arrayElementLowerFragment(elementType: wrappedType) + let _ = innerFragment.printCode([value], scope, printer, localCleanupWriter) + let localCleanupLines = localCleanupWriter.lines.filter { + !$0.trimmingCharacters(in: .whitespaces).isEmpty + } + if !localCleanupLines.isEmpty { + let localCleanupCode = localCleanupLines.joined(separator: " ") + printer.write("arrayCleanups.push(() => { \(localCleanupCode) });") + } + } + printer.write("} else {") + printer.indent { + // Push placeholders so Swift can unconditionally pop value slots + switch wrappedType { + case .float: + printer.write("\(JSGlueVariableScope.reservedTmpParamF32s).push(0.0);") + case .double: + printer.write("\(JSGlueVariableScope.reservedTmpParamF64s).push(0.0);") + case .swiftStruct: + // No placeholder — Swift only pops struct fields when isSome=1 + break + case .string, .rawValueEnum(_, .string): + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(0);") + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(0);") + case .swiftHeapObject: + printer.write("\(JSGlueVariableScope.reservedTmpParamPointers).push(0);") + default: + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(0);") + } + } + printer.write("}") + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar));") + + return [] + } + ) + } + static func structHelper(structDefinition: ExportedStruct, allStructs: [ExportedStruct]) -> IntrinsicJSFragment { return IntrinsicJSFragment( parameters: ["structName"], @@ -2069,10 +2613,10 @@ struct IntrinsicJSFragment: Sendable { printer.write("},") printer.write( - "raise: (\(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s), \(JSGlueVariableScope.reservedTmpRetPointers)) => {" + "lift: (\(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s), \(JSGlueVariableScope.reservedTmpRetPointers)) => {" ) printer.indent { - generateStructRaiseCode( + generateStructLiftCode( structDef: capturedStructDef, allStructs: capturedAllStructs, printer: printer, @@ -2125,21 +2669,21 @@ struct IntrinsicJSFragment: Sendable { } } - private static func generateStructRaiseCode( + private static func generateStructLiftCode( structDef: ExportedStruct, allStructs: [ExportedStruct], printer: CodeFragmentPrinter, attachMethods: Bool = false ) { - let raiseScope = JSGlueVariableScope() - let raiseCleanup = CodeFragmentPrinter() + let liftScope = JSGlueVariableScope() + let liftCleanup = CodeFragmentPrinter() var fieldExpressions: [(name: String, expression: String)] = [] let instanceProps = structDef.properties.filter { !$0.isStatic } for property in instanceProps.reversed() { - let fragment = structFieldRaiseFragment(field: property, allStructs: allStructs) - let results = fragment.printCode([], raiseScope, printer, raiseCleanup) + let fragment = structFieldLiftFragment(field: property, allStructs: allStructs) + let results = fragment.printCode([], liftScope, printer, liftCleanup) if let resultExpr = results.first { fieldExpressions.append((property.name, resultExpr)) @@ -2155,7 +2699,7 @@ struct IntrinsicJSFragment: Sendable { } if attachMethods && !structDef.methods.filter({ !$0.effects.isStatic }).isEmpty { - let instanceVar = raiseScope.variable("instance") + let instanceVar = liftScope.variable("instance") printer.write("const \(instanceVar) = { \(reconstructedFields.joined(separator: ", ")) };") // Attach instance methods to the struct instance @@ -2242,7 +2786,7 @@ struct IntrinsicJSFragment: Sendable { return [] } ) - case .int: + case .int, .uint: return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, scope, printer, cleanup in @@ -2266,6 +2810,14 @@ struct IntrinsicJSFragment: Sendable { return [] } ) + case .unsafePointer: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + printer.write("\(JSGlueVariableScope.reservedTmpParamPointers).push((\(arguments[0]) | 0));") + return [] + } + ) case .jsObject: return IntrinsicJSFragment( parameters: ["value"], @@ -2344,6 +2896,32 @@ struct IntrinsicJSFragment: Sendable { "if(\(idVar) !== undefined) { \(JSGlueVariableScope.reservedSwift).memory.release(\(idVar)); }" ) return [idVar] + case .float: + printer.write("if (\(isSomeVar)) {") + printer.indent { + printer.write( + "\(JSGlueVariableScope.reservedTmpParamF32s).push(Math.fround(\(value)));" + ) + } + printer.write("} else {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedTmpParamF32s).push(0.0);") + } + printer.write("}") + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? 1 : 0);") + return [] + case .double: + printer.write("if (\(isSomeVar)) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedTmpParamF64s).push(\(value));") + } + printer.write("} else {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedTmpParamF64s).push(0.0);") + } + printer.write("}") + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? 1 : 0);") + return [] default: printer.write("if (\(isSomeVar)) {") printer.indent { @@ -2438,7 +3016,7 @@ struct IntrinsicJSFragment: Sendable { } else { // Handle optional primitive types using helper switch wrappedType { - case .int: + case .int, .uint: pushOptionalPrimitive( value: value, isSomeVar: isSomeVar, @@ -2583,6 +3161,22 @@ struct IntrinsicJSFragment: Sendable { return [idVar] } ) + case .float: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + printer.write("\(JSGlueVariableScope.reservedTmpParamF32s).push(Math.fround(\(arguments[0])));") + return [] + } + ) + case .double: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + printer.write("\(JSGlueVariableScope.reservedTmpParamF64s).push(\(arguments[0]));") + return [] + } + ) default: return IntrinsicJSFragment( parameters: ["value"], @@ -2601,6 +3195,8 @@ struct IntrinsicJSFragment: Sendable { return [] } ) + case .array(let elementType): + return try! arrayLower(elementType: elementType) } } @@ -2648,7 +3244,7 @@ struct IntrinsicJSFragment: Sendable { case tmpParamF64s } - private static func structFieldRaiseFragment( + private static func structFieldLiftFragment( field: ExportedProperty, allStructs: [ExportedStruct] ) -> IntrinsicJSFragment { @@ -2671,7 +3267,7 @@ struct IntrinsicJSFragment: Sendable { return [bVar] } ) - case .int: + case .int, .uint: return IntrinsicJSFragment( parameters: [], printCode: { arguments, scope, printer, cleanup in @@ -2698,6 +3294,15 @@ struct IntrinsicJSFragment: Sendable { return [dVar] } ) + case .unsafePointer: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let pVar = scope.variable("pointer") + printer.write("const \(pVar) = \(JSGlueVariableScope.reservedTmpRetPointers).pop();") + return [pVar] + } + ) case .optional(let wrappedType): return IntrinsicJSFragment( parameters: [], @@ -2714,10 +3319,10 @@ struct IntrinsicJSFragment: Sendable { let caseIdVar = scope.variable("enumCaseId") printer.write("const \(caseIdVar) = \(JSGlueVariableScope.reservedTmpRetInts).pop();") printer.write( - "\(optVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).raise(\(caseIdVar), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" + "\(optVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(caseIdVar), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" ) } else { - let wrappedFragment = structFieldRaiseFragment( + let wrappedFragment = structFieldLiftFragment( field: ExportedProperty( name: field.name, type: wrappedType, @@ -2748,7 +3353,7 @@ struct IntrinsicJSFragment: Sendable { printCode: { arguments, scope, printer, cleanup in let structVar = scope.variable("struct") printer.write( - "const \(structVar) = \(JSGlueVariableScope.reservedStructHelpers).\(nestedName).raise(\(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s), \(JSGlueVariableScope.reservedTmpRetPointers));" + "const \(structVar) = \(JSGlueVariableScope.reservedStructHelpers).\(nestedName).lift(\(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s), \(JSGlueVariableScope.reservedTmpRetPointers));" ) return [structVar] } @@ -2773,6 +3378,24 @@ struct IntrinsicJSFragment: Sendable { return [varName] } ) + case .float: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let varName = scope.variable("value") + printer.write("const \(varName) = \(JSGlueVariableScope.reservedTmpRetF32s).pop();") + return [varName] + } + ) + case .double: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let varName = scope.variable("value") + printer.write("const \(varName) = \(JSGlueVariableScope.reservedTmpRetF64s).pop();") + return [varName] + } + ) default: return IntrinsicJSFragment( parameters: [], @@ -2824,7 +3447,7 @@ struct IntrinsicJSFragment: Sendable { printCode: { arguments, scope, printer, cleanup in let varName = scope.variable("value") printer.write( - "const \(varName) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).raise(\(JSGlueVariableScope.reservedTmpRetTag), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" + "const \(varName) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(JSGlueVariableScope.reservedTmpRetTag), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" ) return [varName] } @@ -2838,6 +3461,8 @@ struct IntrinsicJSFragment: Sendable { return [] } ) + case .array(let elementType): + return try! arrayLift(elementType: elementType) } } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSMacros/JSClassMacro.swift b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSClassMacro.swift index 8a3f83f05..2641df4bf 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSMacros/JSClassMacro.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSClassMacro.swift @@ -66,9 +66,16 @@ extension JSClassMacro: ExtensionMacro { conformingTo protocols: [TypeSyntax], in context: some MacroExpansionContext ) throws -> [ExtensionDeclSyntax] { - guard declaration.is(StructDeclSyntax.self) else { return [] } + guard let structDecl = declaration.as(StructDeclSyntax.self) else { return [] } guard !protocols.isEmpty else { return [] } + // Do not add extension if the struct already conforms to _JSBridgedClass + if let clause = structDecl.inheritanceClause, + clause.inheritedTypes.contains(where: { $0.type.trimmed.description == "_JSBridgedClass" }) + { + return [] + } + let conformanceList = protocols.map { $0.trimmed.description }.joined(separator: ", ") return [ try ExtensionDeclSyntax("extension \(type.trimmed): \(raw: conformanceList) {}") diff --git a/Plugins/BridgeJS/Sources/BridgeJSMacros/JSFunctionMacro.swift b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSFunctionMacro.swift index 7dfd635f9..a51bf10c5 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSMacros/JSFunctionMacro.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSFunctionMacro.swift @@ -47,7 +47,7 @@ extension JSFunctionMacro: BodyMacro { context.diagnose( Diagnostic(node: Syntax(declaration), message: JSMacroMessage.unsupportedDeclaration) ) - return [] + return [CodeBlockItemSyntax(stringLiteral: "fatalError(\"@JSFunction init must be inside a type\")")] } let glueName = JSMacroHelper.glueName(baseName: "init", enclosingTypeName: enclosingTypeName) @@ -70,3 +70,19 @@ extension JSFunctionMacro: BodyMacro { return [] } } + +extension JSFunctionMacro: PeerMacro { + /// Emits a diagnostic when @JSFunction is applied to a declaration that is not a function or initializer. + /// BodyMacro is only invoked for declarations with optional code blocks (e.g. functions, initializers), + /// so for vars and other decls we need PeerMacro to run and diagnose. + public static func expansion( + of node: AttributeSyntax, + providingPeersOf declaration: some DeclSyntaxProtocol, + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + if declaration.is(FunctionDeclSyntax.self) { return [] } + if declaration.is(InitializerDeclSyntax.self) { return [] } + context.diagnose(Diagnostic(node: Syntax(declaration), message: JSMacroMessage.unsupportedDeclaration)) + return [] + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSMacros/JSGetterMacro.swift b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSGetterMacro.swift index b996facfa..44c3620cf 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSMacros/JSGetterMacro.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSGetterMacro.swift @@ -60,3 +60,20 @@ extension JSGetterMacro: AccessorMacro { ] } } + +extension JSGetterMacro: PeerMacro { + /// Emits a diagnostic when @JSGetter is applied to a declaration that is not a variable (e.g. a function). + /// AccessorMacro may not be invoked for non-property declarations. For variables with multiple + /// bindings, the compiler emits its own diagnostic; we only diagnose non-variable decls here. + public static func expansion( + of node: AttributeSyntax, + providingPeersOf declaration: some DeclSyntaxProtocol, + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + guard declaration.is(VariableDeclSyntax.self) else { + context.diagnose(Diagnostic(node: Syntax(declaration), message: JSMacroMessage.unsupportedVariable)) + return [] + } + return [] + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSMacros/JSSetterMacro.swift b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSSetterMacro.swift index bb9fd1f21..3c7280079 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSMacros/JSSetterMacro.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSSetterMacro.swift @@ -25,13 +25,23 @@ extension JSSetterMacro: BodyMacro { let rawFunctionName = JSMacroHelper.stripBackticks(functionName) guard rawFunctionName.hasPrefix("set"), rawFunctionName.count > 3 else { context.diagnose(Diagnostic(node: Syntax(declaration), message: JSMacroMessage.invalidSetterName)) - return [] + return [ + CodeBlockItemSyntax( + stringLiteral: + "fatalError(\"@JSSetter function name must start with 'set' followed by a property name\")" + ) + ] } let propertyName = String(rawFunctionName.dropFirst(3)) guard !propertyName.isEmpty else { context.diagnose(Diagnostic(node: Syntax(declaration), message: JSMacroMessage.invalidSetterName)) - return [] + return [ + CodeBlockItemSyntax( + stringLiteral: + "fatalError(\"@JSSetter function name must start with 'set' followed by a property name\")" + ) + ] } // Convert first character to lowercase (e.g., "Foo" -> "foo") @@ -56,7 +66,11 @@ extension JSSetterMacro: BodyMacro { let parameters = functionDecl.signature.parameterClause.parameters guard let firstParam = parameters.first else { context.diagnose(Diagnostic(node: Syntax(declaration), message: JSMacroMessage.setterRequiresParameter)) - return [] + return [ + CodeBlockItemSyntax( + stringLiteral: "fatalError(\"@JSSetter function must have at least one parameter\")" + ) + ] } let paramName = firstParam.secondName ?? firstParam.firstName @@ -69,3 +83,21 @@ extension JSSetterMacro: BodyMacro { return [CodeBlockItemSyntax(stringLiteral: "try \(call)")] } } + +extension JSSetterMacro: PeerMacro { + /// Emits a diagnostic when @JSSetter is applied to a declaration that is not a function. + /// BodyMacro is only invoked for declarations with optional code blocks (e.g. functions). + public static func expansion( + of node: AttributeSyntax, + providingPeersOf declaration: some DeclSyntaxProtocol, + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + guard declaration.is(FunctionDeclSyntax.self) else { + context.diagnose( + Diagnostic(node: Syntax(declaration), message: JSMacroMessage.unsupportedSetterDeclaration) + ) + return [] + } + return [] + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift index 28e4b6dcd..33cc94479 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift @@ -107,9 +107,30 @@ public struct ClosureSignature: Codable, Equatable, Hashable, Sendable { } } +public enum UnsafePointerKind: String, Codable, Equatable, Hashable, Sendable { + case unsafePointer + case unsafeMutablePointer + case unsafeRawPointer + case unsafeMutableRawPointer + case opaquePointer +} + +public struct UnsafePointerType: Codable, Equatable, Hashable, Sendable { + public let kind: UnsafePointerKind + /// The pointee type name for generic pointer types (e.g. `UInt8` for `UnsafePointer`). + public let pointee: String? + + public init(kind: UnsafePointerKind, pointee: String? = nil) { + self.kind = kind + self.pointee = pointee + } +} + public enum BridgeType: Codable, Equatable, Hashable, Sendable { - case int, float, double, string, bool, jsObject(String?), swiftHeapObject(String), void + case int, uint, float, double, string, bool, jsObject(String?), swiftHeapObject(String), void + case unsafePointer(UnsafePointerType) indirect case optional(BridgeType) + indirect case array(BridgeType) case caseEnum(String) case rawValueEnum(String, SwiftEnumRawType) case associatedValueEnum(String) @@ -182,6 +203,7 @@ public enum DefaultValue: Codable, Equatable, Sendable { case object(String) // className for parameterless constructor case objectWithArguments(String, [DefaultValue]) // className, constructor argument values case structLiteral(String, [DefaultValueField]) // structName, field name/value pairs + indirect case array([DefaultValue]) // array literal with element values } public struct Parameter: Codable, Equatable, Sendable { @@ -588,14 +610,34 @@ public struct ExportedSkeleton: Codable { // MARK: - Imported Skeleton +/// Controls where BridgeJS reads imported JS values from. +/// +/// - `global`: Read from `globalThis`. +public enum JSImportFrom: String, Codable { + case global +} + public struct ImportedFunctionSkeleton: Codable { public let name: String + /// The JavaScript function/method name to call, if different from `name`. + public let jsName: String? + /// Where this function is looked up from in JavaScript. + public let from: JSImportFrom? public let parameters: [Parameter] public let returnType: BridgeType public let documentation: String? - public init(name: String, parameters: [Parameter], returnType: BridgeType, documentation: String? = nil) { + public init( + name: String, + jsName: String? = nil, + from: JSImportFrom? = nil, + parameters: [Parameter], + returnType: BridgeType, + documentation: String? = nil + ) { self.name = name + self.jsName = jsName + self.from = from self.parameters = parameters self.returnType = returnType self.documentation = documentation @@ -626,6 +668,10 @@ public struct ImportedConstructorSkeleton: Codable { public struct ImportedGetterSkeleton: Codable { public let name: String + /// The JavaScript property name to read from, if different from `name`. + public let jsName: String? + /// Where this property is looked up from in JavaScript (only used for global getters). + public let from: JSImportFrom? public let type: BridgeType public let documentation: String? /// Name of the getter function if it's a separate function (from @JSGetter) @@ -633,11 +679,15 @@ public struct ImportedGetterSkeleton: Codable { public init( name: String, + jsName: String? = nil, + from: JSImportFrom? = nil, type: BridgeType, documentation: String? = nil, functionName: String? = nil ) { self.name = name + self.jsName = jsName + self.from = from self.type = type self.documentation = documentation self.functionName = functionName @@ -661,6 +711,8 @@ public struct ImportedGetterSkeleton: Codable { public struct ImportedSetterSkeleton: Codable { public let name: String + /// The JavaScript property name to write to, if different from `name`. + public let jsName: String? public let type: BridgeType public let documentation: String? /// Name of the setter function if it's a separate function (from @JSSetter) @@ -668,11 +720,13 @@ public struct ImportedSetterSkeleton: Codable { public init( name: String, + jsName: String? = nil, type: BridgeType, documentation: String? = nil, functionName: String? = nil ) { self.name = name + self.jsName = jsName self.type = type self.documentation = documentation self.functionName = functionName @@ -696,6 +750,10 @@ public struct ImportedSetterSkeleton: Codable { public struct ImportedTypeSkeleton: Codable { public let name: String + /// The JavaScript constructor name to use for `init(...)`, if different from `name`. + public let jsName: String? + /// Where this constructor is looked up from in JavaScript. + public let from: JSImportFrom? public let constructor: ImportedConstructorSkeleton? public let methods: [ImportedFunctionSkeleton] public let getters: [ImportedGetterSkeleton] @@ -704,6 +762,8 @@ public struct ImportedTypeSkeleton: Codable { public init( name: String, + jsName: String? = nil, + from: JSImportFrom? = nil, constructor: ImportedConstructorSkeleton? = nil, methods: [ImportedFunctionSkeleton], getters: [ImportedGetterSkeleton] = [], @@ -711,6 +771,8 @@ public struct ImportedTypeSkeleton: Codable { documentation: String? = nil ) { self.name = name + self.jsName = jsName + self.from = from self.constructor = constructor self.methods = methods self.getters = getters @@ -798,6 +860,8 @@ extension BridgeType { switch swiftType { case "Int": self = .int + case "UInt": + self = .uint case "Float": self = .float case "Double": @@ -810,6 +874,12 @@ extension BridgeType { self = .void case "JSObject": self = .jsObject(nil) + case "UnsafeRawPointer": + self = .unsafePointer(.init(kind: .unsafeRawPointer)) + case "UnsafeMutableRawPointer": + self = .unsafePointer(.init(kind: .unsafeMutableRawPointer)) + case "OpaquePointer": + self = .unsafePointer(.init(kind: .opaquePointer)) default: return nil } @@ -819,7 +889,7 @@ extension BridgeType { switch self { case .void: return nil case .bool: return .i32 - case .int: return .i32 + case .int, .uint: return .i32 case .float: return .f32 case .double: return .f64 case .string: return nil @@ -827,6 +897,8 @@ extension BridgeType { case .swiftHeapObject: // UnsafeMutableRawPointer is returned as an i32 pointer return .pointer + case .unsafePointer: + return .pointer case .optional(_): return nil case .caseEnum: @@ -846,6 +918,9 @@ extension BridgeType { case .closure: // Closures pass callback ID as Int32 return .i32 + case .array: + // Arrays use stack-based return with length prefix (no direct WASM return type) + return nil } } @@ -860,6 +935,7 @@ extension BridgeType { public var mangleTypeName: String { switch self { case .int: return "Si" + case .uint: return "Su" case .float: return "Sf" case .double: return "Sd" case .string: return "SS" @@ -870,6 +946,23 @@ extension BridgeType { return "\(typeName.count)\(typeName)C" case .swiftHeapObject(let name): return "\(name.count)\(name)C" + case .unsafePointer(let ptr): + func sanitize(_ s: String) -> String { + s.filter { $0.isNumber || $0.isLetter } + } + let kindCode: String = + switch ptr.kind { + case .unsafePointer: "Sup" + case .unsafeMutablePointer: "Sump" + case .unsafeRawPointer: "Surp" + case .unsafeMutableRawPointer: "Sumrp" + case .opaquePointer: "Sop" + } + if let pointee = ptr.pointee, !pointee.isEmpty { + let p = sanitize(pointee) + return "\(kindCode)\(p.count)\(p)" + } + return kindCode case .optional(let wrapped): return "Sq\(wrapped.mangleTypeName)" case .caseEnum(let name), @@ -887,6 +980,9 @@ extension BridgeType { ? "y" : signature.parameters.map { $0.mangleTypeName }.joined() return "K\(params)_\(signature.returnType.mangleTypeName)" + case .array(let elementType): + // Array mangling: "Sa" prefix followed by element type + return "Sa\(elementType.mangleTypeName)" } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift b/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift index 3fb7f8114..dd37fb3bc 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift @@ -110,21 +110,38 @@ import BridgeJSUtilities let nodePath: URL = try config.findTool("node", targetDirectory: targetDirectory) let bridgeJsDtsPath = targetDirectory.appending(path: "bridge-js.d.ts") - if FileManager.default.fileExists(atPath: bridgeJsDtsPath.path) { + let bridgeJsGlobalDtsPath = targetDirectory.appending(path: "bridge-js.global.d.ts") + let hasDts = FileManager.default.fileExists(atPath: bridgeJsDtsPath.path) + let hasGlobalDts = FileManager.default.fileExists(atPath: bridgeJsGlobalDtsPath.path) + var generatedMacrosPath: String? = nil + if hasDts || hasGlobalDts { guard let tsconfigPath = doubleDashOptions["project"] else { throw BridgeJSToolError("--project option is required when processing .d.ts files") } let bridgeJSMacrosPath = outputDirectory.appending(path: "BridgeJS.Macros.swift") + let primaryDtsPath = hasDts ? bridgeJsDtsPath.path : bridgeJsGlobalDtsPath.path + let globalDtsFiles = (hasDts && hasGlobalDts) ? [bridgeJsGlobalDtsPath.path] : [] _ = try invokeTS2Swift( - dtsFile: bridgeJsDtsPath.path, + dtsFile: primaryDtsPath, + globalDtsFiles: globalDtsFiles, tsconfigPath: tsconfigPath, nodePath: nodePath, progress: progress, outputPath: bridgeJSMacrosPath.path ) + generatedMacrosPath = bridgeJSMacrosPath.path } - let inputFiles = inputSwiftFiles(targetDirectory: targetDirectory, positionalArguments: positionalArguments) + var inputFiles = 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. + if let macrosPath = generatedMacrosPath, FileManager.default.fileExists(atPath: macrosPath) { + // Only add if not already present (when running directly vs through plugin) + if !inputFiles.contains(macrosPath) { + inputFiles.append(macrosPath) + } + } let swiftToSkeleton = SwiftToSkeleton( progress: progress, moduleName: moduleName, diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js index 28f37e0ec..645be1f5a 100644 --- a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js @@ -73,7 +73,7 @@ class DiagnosticEngine { } function printUsage() { - console.error('Usage: ts2swift -p [-o output.swift]'); + console.error('Usage: ts2swift -p [--global ]... [-o output.swift]'); } /** @@ -94,6 +94,10 @@ export function main(args) { type: 'string', short: 'p', }, + global: { + type: 'string', + multiple: true, + }, "log-level": { type: 'string', default: 'info', @@ -131,15 +135,44 @@ export function main(args) { process.exit(1); } - const program = TypeProcessor.createProgram(filePath, configParseResult.options); + /** @type {string[]} */ + const globalFiles = Array.isArray(options.values.global) + ? options.values.global + : (options.values.global ? [options.values.global] : []); + + const program = TypeProcessor.createProgram([filePath, ...globalFiles], configParseResult.options); const diagnostics = program.getSemanticDiagnostics(); if (diagnostics.length > 0) { diagnosticEngine.tsDiagnose(diagnostics); process.exit(1); } - const processor = new TypeProcessor(program.getTypeChecker(), diagnosticEngine); - const { content: swiftOutput, hasAny } = processor.processTypeDeclarations(program, filePath); + const prelude = [ + "// 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) import JavaScriptKit", + "", + "", + ].join("\n"); + + /** @type {string[]} */ + const bodies = []; + const globalFileSet = new Set(globalFiles); + for (const inputPath of [filePath, ...globalFiles]) { + const processor = new TypeProcessor(program.getTypeChecker(), diagnosticEngine, { + defaultImportFromGlobal: globalFileSet.has(inputPath), + }); + const result = processor.processTypeDeclarations(program, inputPath); + const body = result.content.trim(); + if (body.length > 0) bodies.push(body); + } + + const hasAny = bodies.length > 0; + const swiftOutput = hasAny ? prelude + bodies.join("\n\n") + "\n" : ""; if (options.values.output) { if (hasAny) { diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/processor.js b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/processor.js index 6a752ab80..e48510466 100644 --- a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/processor.js +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/processor.js @@ -24,9 +24,10 @@ export class TypeProcessor { * @param {ts.CompilerOptions} options - Compiler options * @returns {ts.Program} TypeScript program object */ - static createProgram(filePath, options) { + static createProgram(filePaths, options) { const host = ts.createCompilerHost(options); - return ts.createProgram([filePath], options, host); + const roots = Array.isArray(filePaths) ? filePaths : [filePaths]; + return ts.createProgram(roots, options, host); } /** @@ -60,6 +61,70 @@ export class TypeProcessor { /** @type {Set} */ this.visitedDeclarationKeys = new Set(); + + /** @type {Map} */ + this.swiftTypeNameByJSTypeName = new Map(); + + /** @type {boolean} */ + this.defaultImportFromGlobal = options.defaultImportFromGlobal ?? false; + } + + /** + * Escape a string for a Swift string literal inside macro arguments. + * @param {string} value + * @returns {string} + * @private + */ + escapeForSwiftStringLiteral(value) { + return value.replaceAll("\\", "\\\\").replaceAll("\"", "\\\\\""); + } + + /** + * Render a `jsName:` macro argument if the JS name differs from the default. + * @param {string} jsName + * @param {string} defaultName + * @returns {string | null} + * @private + */ + renderOptionalJSNameArg(jsName, defaultName) { + if (jsName === defaultName) return null; + return `jsName: "${this.escapeForSwiftStringLiteral(jsName)}"`; + } + + /** + * Render a macro annotation with optional labeled arguments. + * @param {string} macroName + * @param {string[]} args + * @returns {string} + * @private + */ + renderMacroAnnotation(macroName, args) { + if (!args.length) return `@${macroName}`; + return `@${macroName}(${args.join(", ")})`; + } + + /** + * Convert a TypeScript type name to a valid Swift type identifier. + * @param {string} jsTypeName + * @returns {string} + * @private + */ + swiftTypeName(jsTypeName) { + const cached = this.swiftTypeNameByJSTypeName.get(jsTypeName); + if (cached) return cached; + const swiftName = isValidSwiftDeclName(jsTypeName) ? jsTypeName : makeValidSwiftIdentifier(jsTypeName, { emptyFallback: "_" }); + this.swiftTypeNameByJSTypeName.set(jsTypeName, swiftName); + return swiftName; + } + + /** + * Render a Swift type identifier from a TypeScript type name. + * @param {string} jsTypeName + * @returns {string} + * @private + */ + renderTypeIdentifier(jsTypeName) { + return this.renderIdentifier(this.swiftTypeName(jsTypeName)); } /** @@ -73,18 +138,6 @@ export class TypeProcessor { sf => !sf.isDeclarationFile || sf.fileName === inputFilePath ); - // Add prelude - this.swiftLines.push( - "// 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) import JavaScriptKit", - "" - ); - for (const sourceFile of sourceFiles) { if (sourceFile.fileName.includes('node_modules/typescript/lib')) continue; @@ -113,7 +166,7 @@ export class TypeProcessor { } const content = this.swiftLines.join("\n").trimEnd() + "\n"; - const hasAny = this.swiftLines.length > 9; // More than just the prelude + const hasAny = content.trim().length > 0; return { content, hasAny }; } @@ -127,6 +180,8 @@ export class TypeProcessor { this.visitFunctionDeclaration(node); } else if (ts.isClassDeclaration(node)) { this.visitClassDecl(node); + } else if (ts.isVariableStatement(node)) { + this.visitVariableStatement(node); } else if (ts.isEnumDeclaration(node)) { this.visitEnumDeclaration(node); } else if (ts.isExportDeclaration(node)) { @@ -195,6 +250,41 @@ export class TypeProcessor { } } + /** + * Visit an exported variable statement and render Swift global getter(s). + * Supports simple `export const foo: T` / `export let foo: T` declarations. + * + * @param {ts.VariableStatement} node + * @private + */ + visitVariableStatement(node) { + const isExported = node.modifiers?.some(m => m.kind === ts.SyntaxKind.ExportKeyword) ?? false; + if (!isExported) return; + + const fromArg = this.renderDefaultJSImportFromArgument(); + + for (const decl of node.declarationList.declarations) { + if (!ts.isIdentifier(decl.name)) continue; + + const jsName = decl.name.text; + const swiftName = this.swiftTypeName(jsName); + const swiftVarName = this.renderIdentifier(swiftName); + + const type = this.checker.getTypeAtLocation(decl); + const swiftType = this.visitType(type, decl); + + /** @type {string[]} */ + const args = []; + const jsNameArg = this.renderOptionalJSNameArg(jsName, swiftName); + if (jsNameArg) args.push(jsNameArg); + if (fromArg) args.push(fromArg); + const annotation = this.renderMacroAnnotation("JSGetter", args); + + this.swiftLines.push(`${annotation} var ${swiftVarName}: ${swiftType}`); + this.swiftLines.push(""); + } + } + /** * @param {ts.Type} type * @returns {boolean} @@ -292,7 +382,7 @@ export class TypeProcessor { canBeStringEnum = false; canBeIntEnum = false; } - const swiftEnumName = this.renderIdentifier(enumName); + const swiftEnumName = this.renderTypeIdentifier(enumName); const dedupeNames = (items) => { const seen = new Map(); return items.map(item => { @@ -341,10 +431,15 @@ export class TypeProcessor { */ visitFunctionDeclaration(node) { if (!node.name) return; - const name = node.name.getText(); - if (!isValidSwiftDeclName(name)) { - return; - } + const jsName = node.name.text; + const swiftName = this.swiftTypeName(jsName); + const fromArg = this.renderDefaultJSImportFromArgument(); + /** @type {string[]} */ + const args = []; + const jsNameArg = this.renderOptionalJSNameArg(jsName, swiftName); + if (jsNameArg) args.push(jsNameArg); + if (fromArg) args.push(fromArg); + const annotation = this.renderMacroAnnotation("JSFunction", args); const signature = this.checker.getSignatureFromDeclaration(node); if (!signature) return; @@ -352,9 +447,9 @@ export class TypeProcessor { const params = this.renderParameters(signature.getParameters(), node); const returnType = this.visitType(signature.getReturnType(), node); const effects = this.renderEffects({ isAsync: false }); - const swiftName = this.renderIdentifier(name); + const swiftFuncName = this.renderIdentifier(swiftName); - this.swiftLines.push(`@JSFunction func ${swiftName}(${params}) ${effects} -> ${returnType}`); + this.swiftLines.push(`${annotation} func ${swiftFuncName}(${params}) ${effects} -> ${returnType}`); this.swiftLines.push(""); } @@ -375,6 +470,12 @@ export class TypeProcessor { return parts.join("\n"); } + /** @returns {string} */ + renderDefaultJSImportFromArgument() { + if (this.defaultImportFromGlobal) return "from: .global"; + return ""; + } + /** * Render constructor parameters * @param {ts.ConstructorDeclaration} node @@ -390,21 +491,28 @@ export class TypeProcessor { /** * @param {ts.PropertyDeclaration | ts.PropertySignature} node - * @returns {{ name: string, type: string, isReadonly: boolean, documentation: string | undefined } | null} + * @returns {{ jsName: string, swiftName: string, type: string, isReadonly: boolean, documentation: string | undefined } | null} */ visitPropertyDecl(node) { if (!node.name) return null; - - const propertyName = node.name.getText(); - if (!isValidSwiftDeclName(propertyName)) { + /** @type {string | null} */ + let jsName = null; + if (ts.isIdentifier(node.name)) { + jsName = node.name.text; + } else if (ts.isStringLiteral(node.name) || ts.isNumericLiteral(node.name)) { + jsName = node.name.text; + } else { + // Computed property names like `[Symbol.iterator]` are not supported yet. return null; } + const swiftName = isValidSwiftDeclName(jsName) ? jsName : makeValidSwiftIdentifier(jsName, { emptyFallback: "_" }); + const type = this.checker.getTypeAtLocation(node) const swiftType = this.visitType(type, node); const isReadonly = node.modifiers?.some(m => m.kind === ts.SyntaxKind.ReadonlyKeyword) ?? false; const documentation = this.getFullJSDocText(node); - return { name: propertyName, type: swiftType, isReadonly, documentation }; + return { jsName, swiftName, type: swiftType, isReadonly, documentation }; } /** @@ -426,8 +534,20 @@ export class TypeProcessor { visitClassDecl(node) { if (!node.name) return; - const className = this.renderIdentifier(node.name.text); - this.swiftLines.push(`@JSClass struct ${className} {`); + const jsName = node.name.text; + if (this.emittedStructuredTypeNames.has(jsName)) return; + this.emittedStructuredTypeNames.add(jsName); + + const swiftName = this.swiftTypeName(jsName); + const fromArg = this.renderDefaultJSImportFromArgument(); + /** @type {string[]} */ + const args = []; + const jsNameArg = this.renderOptionalJSNameArg(jsName, swiftName); + if (jsNameArg) args.push(jsNameArg); + if (fromArg) args.push(fromArg); + const annotation = this.renderMacroAnnotation("JSClass", args); + const className = this.renderIdentifier(swiftName); + this.swiftLines.push(`${annotation} struct ${className} {`); // Process members in declaration order for (const member of node.members) { @@ -484,8 +604,14 @@ export class TypeProcessor { if (this.emittedStructuredTypeNames.has(name)) return; this.emittedStructuredTypeNames.add(name); - const typeName = this.renderIdentifier(name); - this.swiftLines.push(`@JSClass struct ${typeName} {`); + const swiftName = this.swiftTypeName(name); + /** @type {string[]} */ + const args = []; + const jsNameArg = this.renderOptionalJSNameArg(name, swiftName); + if (jsNameArg) args.push(jsNameArg); + const annotation = this.renderMacroAnnotation("JSClass", args); + const typeName = this.renderIdentifier(swiftName); + this.swiftLines.push(`${annotation} struct ${typeName} {`); // Collect all declarations with their positions to preserve order /** @type {Array<{ decl: ts.Node, symbol: ts.Symbol, position: number }>} */ @@ -571,7 +697,7 @@ export class TypeProcessor { if (symbol && (symbol.flags & ts.SymbolFlags.Enum) !== 0) { const typeName = symbol.name; this.seenTypes.set(type, node); - return this.renderIdentifier(typeName); + return this.renderTypeIdentifier(typeName); } if (this.checker.isArrayType(type) || this.checker.isTupleType(type) || type.getCallSignatures().length > 0) { @@ -591,7 +717,7 @@ export class TypeProcessor { return "JSObject"; } this.seenTypes.set(type, node); - return this.renderIdentifier(typeName); + return this.renderTypeIdentifier(typeName); } const swiftType = convert(type); this.processedTypes.set(type, swiftType); @@ -626,17 +752,31 @@ export class TypeProcessor { if (!property) return; const type = property.type; - const name = this.renderIdentifier(property.name); + const swiftName = this.renderIdentifier(property.swiftName); + const needsJSGetterName = property.jsName !== property.swiftName; + // Note: `from: .global` is only meaningful for top-level imports and constructors. + // Instance member access always comes from the JS object itself. + const fromArg = ""; + /** @type {string[]} */ + const getterArgs = []; + if (needsJSGetterName) getterArgs.push(`jsName: "${this.escapeForSwiftStringLiteral(property.jsName)}"`); + if (fromArg) getterArgs.push(fromArg); + const getterAnnotation = this.renderMacroAnnotation("JSGetter", getterArgs); // Always render getter - this.swiftLines.push(` @JSGetter var ${name}: ${type}`); + this.swiftLines.push(` ${getterAnnotation} var ${swiftName}: ${type}`); // Render setter if not readonly if (!property.isReadonly) { - const capitalizedName = property.name.charAt(0).toUpperCase() + property.name.slice(1); - const needsJSNameField = property.name.charAt(0) != capitalizedName.charAt(0).toLowerCase(); - const setterName = `set${capitalizedName}`; - const annotation = needsJSNameField ? `@JSSetter(jsName: "${property.name}")` : "@JSSetter"; + const capitalizedSwiftName = property.swiftName.charAt(0).toUpperCase() + property.swiftName.slice(1); + const derivedPropertyName = property.swiftName.charAt(0).toLowerCase() + property.swiftName.slice(1); + const needsJSNameField = property.jsName !== derivedPropertyName; + const setterName = `set${capitalizedSwiftName}`; + /** @type {string[]} */ + const setterArgs = []; + if (needsJSNameField) setterArgs.push(`jsName: "${this.escapeForSwiftStringLiteral(property.jsName)}"`); + if (fromArg) setterArgs.push(fromArg); + const annotation = this.renderMacroAnnotation("JSSetter", setterArgs); this.swiftLines.push(` ${annotation} func ${this.renderIdentifier(setterName)}(_ value: ${type}) ${this.renderEffects({ isAsync: false })}`); } } @@ -648,8 +788,27 @@ export class TypeProcessor { */ renderMethod(node) { if (!node.name) return; - const name = node.name.getText(); - if (!isValidSwiftDeclName(name)) return; + /** @type {string | null} */ + let jsName = null; + if (ts.isIdentifier(node.name)) { + jsName = node.name.text; + } else if (ts.isStringLiteral(node.name) || ts.isNumericLiteral(node.name)) { + jsName = node.name.text; + } else { + // Computed property names like `[Symbol.iterator]` are not supported yet. + return; + } + + const swiftName = this.swiftTypeName(jsName); + const needsJSNameField = jsName !== swiftName; + // Note: `from: .global` is only meaningful for top-level imports and constructors. + // Instance member calls always come from the JS object itself. + const fromArg = ""; + /** @type {string[]} */ + const args = []; + if (needsJSNameField) args.push(`jsName: "${this.escapeForSwiftStringLiteral(jsName)}"`); + if (fromArg) args.push(fromArg); + const annotation = this.renderMacroAnnotation("JSFunction", args); const signature = this.checker.getSignatureFromDeclaration(node); if (!signature) return; @@ -657,9 +816,9 @@ export class TypeProcessor { const params = this.renderParameters(signature.getParameters(), node); const returnType = this.visitType(signature.getReturnType(), node); const effects = this.renderEffects({ isAsync: false }); - const swiftName = this.renderIdentifier(name); + const swiftMethodName = this.renderIdentifier(swiftName); - this.swiftLines.push(` @JSFunction func ${swiftName}(${params}) ${effects} -> ${returnType}`); + this.swiftLines.push(` ${annotation} func ${swiftMethodName}(${params}) ${effects} -> ${returnType}`); } /** diff --git a/Plugins/BridgeJS/Sources/TS2Swift/TS2Swift.swift b/Plugins/BridgeJS/Sources/TS2Swift/TS2Swift.swift index 0a69eb702..795b7b390 100644 --- a/Plugins/BridgeJS/Sources/TS2Swift/TS2Swift.swift +++ b/Plugins/BridgeJS/Sources/TS2Swift/TS2Swift.swift @@ -87,6 +87,7 @@ extension BridgeJSConfig { /// - Returns: The generated Swift source code (always collected from stdout for return value) public func invokeTS2Swift( dtsFile: String, + globalDtsFiles: [String] = [], tsconfigPath: String, nodePath: URL, progress: ProgressReporting, @@ -98,6 +99,9 @@ public func invokeTS2Swift( .appendingPathComponent("bin") .appendingPathComponent("ts2swift.js") var arguments = [ts2swiftPath.path, dtsFile, "--project", tsconfigPath] + for global in globalDtsFiles { + arguments.append(contentsOf: ["--global", global]) + } if let outputPath = outputPath { arguments.append(contentsOf: ["--output", outputPath]) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSClassMacroTests.swift b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSClassMacroTests.swift index b27b93941..7640916e4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSClassMacroTests.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSClassMacroTests.swift @@ -1,8 +1,7 @@ import SwiftDiagnostics import SwiftSyntax import SwiftSyntaxMacroExpansion -import SwiftSyntaxMacros -import SwiftSyntaxMacrosTestSupport +import SwiftSyntaxMacrosGenericTestSupport import Testing import BridgeJSMacros @@ -13,7 +12,7 @@ import BridgeJSMacros ] @Test func emptyStruct() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSClass struct MyClass { @@ -21,6 +20,7 @@ import BridgeJSMacros """, expandedSource: """ struct MyClass { + let jsObject: JSObject init(unsafelyWrapping jsObject: JSObject) { @@ -32,12 +32,12 @@ import BridgeJSMacros } """, macroSpecs: macroSpecs, - indentationWidth: indentationWidth + indentationWidth: indentationWidth, ) } @Test func structWithExistingJSObject() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSClass struct MyClass { @@ -62,7 +62,7 @@ import BridgeJSMacros } @Test func structWithExistingInit() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSClass struct MyClass { @@ -73,11 +73,11 @@ import BridgeJSMacros """, expandedSource: """ struct MyClass { - let jsObject: JSObject - init(unsafelyWrapping jsObject: JSObject) { self.jsObject = jsObject } + + let jsObject: JSObject } extension MyClass: _JSBridgedClass { @@ -89,7 +89,7 @@ import BridgeJSMacros } @Test func structWithBothExisting() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSClass struct MyClass { @@ -118,7 +118,7 @@ import BridgeJSMacros } @Test func structWithMembers() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSClass struct MyClass { @@ -127,10 +127,10 @@ import BridgeJSMacros """, expandedSource: """ struct MyClass { - let jsObject: JSObject - var name: String + let jsObject: JSObject + init(unsafelyWrapping jsObject: JSObject) { self.jsObject = jsObject } @@ -145,7 +145,7 @@ import BridgeJSMacros } @Test func _class() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSClass class MyClass { @@ -168,7 +168,7 @@ import BridgeJSMacros } @Test func _enum() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSClass enum MyEnum { @@ -191,7 +191,7 @@ import BridgeJSMacros } @Test func _actor() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSClass actor MyActor { @@ -214,7 +214,7 @@ import BridgeJSMacros } @Test func structWithDifferentJSObjectName() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSClass struct MyClass { @@ -223,10 +223,10 @@ import BridgeJSMacros """, expandedSource: """ struct MyClass { - let jsObject: JSObject - var otherProperty: String + let jsObject: JSObject + init(unsafelyWrapping jsObject: JSObject) { self.jsObject = jsObject } @@ -241,7 +241,7 @@ import BridgeJSMacros } @Test func structWithDifferentInit() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSClass struct MyClass { @@ -251,11 +251,11 @@ import BridgeJSMacros """, expandedSource: """ struct MyClass { - let jsObject: JSObject - init(name: String) { } + let jsObject: JSObject + init(unsafelyWrapping jsObject: JSObject) { self.jsObject = jsObject } @@ -270,7 +270,7 @@ import BridgeJSMacros } @Test func structWithMultipleMembers() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSClass struct MyClass { @@ -280,11 +280,11 @@ import BridgeJSMacros """, expandedSource: """ struct MyClass { - let jsObject: JSObject - var name: String var age: Int + let jsObject: JSObject + init(unsafelyWrapping jsObject: JSObject) { self.jsObject = jsObject } @@ -299,7 +299,7 @@ import BridgeJSMacros } @Test func structWithComment() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ /// Documentation comment @JSClass @@ -309,6 +309,7 @@ import BridgeJSMacros expandedSource: """ /// Documentation comment struct MyClass { + let jsObject: JSObject init(unsafelyWrapping jsObject: JSObject) { @@ -325,7 +326,7 @@ import BridgeJSMacros } @Test func structAlreadyConforms() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSClass struct MyClass: _JSBridgedClass { @@ -333,6 +334,7 @@ import BridgeJSMacros """, expandedSource: """ struct MyClass: _JSBridgedClass { + let jsObject: JSObject init(unsafelyWrapping jsObject: JSObject) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSFunctionMacroTests.swift b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSFunctionMacroTests.swift index 8cfdd66e0..756935e7d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSFunctionMacroTests.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSFunctionMacroTests.swift @@ -1,15 +1,18 @@ import SwiftDiagnostics import SwiftSyntax -import SwiftSyntaxMacros -import SwiftSyntaxMacrosTestSupport +import SwiftSyntaxMacroExpansion +import SwiftSyntaxMacrosGenericTestSupport import Testing import BridgeJSMacros @Suite struct JSFunctionMacroTests { private let indentationWidth: Trivia = .spaces(4) + private let macroSpecs: [String: MacroSpec] = [ + "JSFunction": MacroSpec(type: JSFunctionMacro.self) + ] @Test func topLevelFunction() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSFunction func greet(name: String) -> String @@ -19,13 +22,13 @@ import BridgeJSMacros return _$greet(name) } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func topLevelFunctionVoidReturn() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSFunction func log(message: String) @@ -35,13 +38,13 @@ import BridgeJSMacros _$log(message) } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func topLevelFunctionWithExplicitVoidReturn() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSFunction func log(message: String) -> Void @@ -51,13 +54,13 @@ import BridgeJSMacros _$log(message) } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func topLevelFunctionWithEmptyTupleReturn() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSFunction func log(message: String) -> () @@ -67,13 +70,13 @@ import BridgeJSMacros _$log(message) } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func topLevelFunctionThrows() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSFunction func parse(json: String) throws -> [String: Any] @@ -83,13 +86,13 @@ import BridgeJSMacros return try _$parse(json) } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func topLevelFunctionAsync() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSFunction func fetch(url: String) async -> String @@ -99,13 +102,13 @@ import BridgeJSMacros return await _$fetch(url) } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func topLevelFunctionAsyncThrows() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSFunction func fetch(url: String) async throws -> String @@ -115,13 +118,13 @@ import BridgeJSMacros return try await _$fetch(url) } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func topLevelFunctionWithUnderscoreParameter() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSFunction func process(_ value: Int) -> Int @@ -131,13 +134,13 @@ import BridgeJSMacros return _$process(value) } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func topLevelFunctionWithMultipleParameters() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSFunction func add(a: Int, b: Int) -> Int @@ -147,13 +150,13 @@ import BridgeJSMacros return _$add(a, b) } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func instanceMethod() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ struct MyClass { @JSFunction @@ -167,13 +170,13 @@ import BridgeJSMacros } } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func staticMethod() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ struct MyClass { @JSFunction @@ -183,17 +186,17 @@ import BridgeJSMacros expandedSource: """ struct MyClass { static func create() -> MyClass { - return _$create() + return _$MyClass_create() } } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func classMethod() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ class MyClass { @JSFunction @@ -203,17 +206,17 @@ import BridgeJSMacros expandedSource: """ class MyClass { class func create() -> MyClass { - return _$create() + return _$MyClass_create() } } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func initializer() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ struct MyClass { @JSFunction @@ -228,13 +231,13 @@ import BridgeJSMacros } } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func initializerThrows() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ struct MyClass { @JSFunction @@ -249,13 +252,13 @@ import BridgeJSMacros } } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func initializerAsyncThrows() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ struct MyClass { @JSFunction @@ -270,19 +273,21 @@ import BridgeJSMacros } } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func initializerWithoutEnclosingType() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSFunction init() """, expandedSource: """ - init() + init() { + fatalError("@JSFunction init must be inside a type") + } """, diagnostics: [ DiagnosticSpec( @@ -291,13 +296,13 @@ import BridgeJSMacros column: 1 ) ], - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func unsupportedDeclaration() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSFunction var property: String @@ -312,13 +317,13 @@ import BridgeJSMacros column: 1 ) ], - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func enumInstanceMethod() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ enum MyEnum { @JSFunction @@ -332,13 +337,13 @@ import BridgeJSMacros } } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func actorInstanceMethod() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ actor MyActor { @JSFunction @@ -352,13 +357,13 @@ import BridgeJSMacros } } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func functionWithExistingBody() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSFunction func greet(name: String) -> String { @@ -370,8 +375,8 @@ import BridgeJSMacros return _$greet(name) } """, - macros: ["JSFunction": JSFunctionMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSGetterMacroTests.swift b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSGetterMacroTests.swift index 8c7f3c119..2796c1014 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSGetterMacroTests.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSGetterMacroTests.swift @@ -1,15 +1,18 @@ import SwiftDiagnostics import SwiftSyntax -import SwiftSyntaxMacros -import SwiftSyntaxMacrosTestSupport +import SwiftSyntaxMacroExpansion +import SwiftSyntaxMacrosGenericTestSupport import Testing import BridgeJSMacros @Suite struct JSGetterMacroTests { private let indentationWidth: Trivia = .spaces(4) + private let macroSpecs: [String: MacroSpec] = [ + "JSGetter": MacroSpec(type: JSGetterMacro.self) + ] @Test func topLevelVariable() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSGetter var count: Int @@ -21,13 +24,13 @@ import BridgeJSMacros } } """, - macros: ["JSGetter": JSGetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func topLevelLet() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSGetter let constant: String @@ -39,13 +42,13 @@ import BridgeJSMacros } } """, - macros: ["JSGetter": JSGetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func instanceProperty() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ struct MyClass { @JSGetter @@ -61,13 +64,13 @@ import BridgeJSMacros } } """, - macros: ["JSGetter": JSGetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func instanceLetProperty() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ struct MyClass { @JSGetter @@ -83,13 +86,13 @@ import BridgeJSMacros } } """, - macros: ["JSGetter": JSGetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func staticProperty() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ struct MyClass { @JSGetter @@ -100,18 +103,18 @@ import BridgeJSMacros struct MyClass { static var version: String { get throws(JSException) { - return try _$version_get() + return try _$MyClass_version_get() } } } """, - macros: ["JSGetter": JSGetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func classProperty() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ class MyClass { @JSGetter @@ -122,18 +125,18 @@ import BridgeJSMacros class MyClass { class var version: String { get throws(JSException) { - return try _$version_get() + return try _$MyClass_version_get() } } } """, - macros: ["JSGetter": JSGetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func enumProperty() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ enum MyEnum { @JSGetter @@ -149,13 +152,13 @@ import BridgeJSMacros } } """, - macros: ["JSGetter": JSGetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func actorProperty() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ actor MyActor { @JSGetter @@ -171,13 +174,13 @@ import BridgeJSMacros } } """, - macros: ["JSGetter": JSGetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func variableWithExistingAccessor() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSGetter var count: Int { @@ -194,13 +197,13 @@ import BridgeJSMacros } } """, - macros: ["JSGetter": JSGetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func variableWithInitializer() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSGetter var count: Int = 0 @@ -212,13 +215,13 @@ import BridgeJSMacros } } """, - macros: ["JSGetter": JSGetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func multipleBindings() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSGetter var x: Int, y: Int @@ -228,19 +231,25 @@ import BridgeJSMacros """, diagnostics: [ DiagnosticSpec( - message: "@JSGetter can only be applied to single-variable declarations.", + message: "accessor macro can only be applied to a single variable", line: 1, column: 1, severity: .error - ) + ), + DiagnosticSpec( + message: "peer macro can only be applied to a single variable", + line: 1, + column: 1, + severity: .error + ), ], - macros: ["JSGetter": JSGetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func unsupportedDeclaration() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSGetter func test() {} @@ -256,13 +265,15 @@ import BridgeJSMacros severity: .error ) ], - macros: ["JSGetter": JSGetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } + #if canImport(SwiftSyntax601) + // https://github.com/swiftlang/swift-syntax/pull/2722 @Test func variableWithTrailingComment() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSGetter var count: Int // comment @@ -274,13 +285,14 @@ import BridgeJSMacros } } """, - macros: ["JSGetter": JSGetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } + #endif @Test func variableWithUnderscoreName() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSGetter var _internal: String @@ -288,12 +300,12 @@ import BridgeJSMacros expandedSource: """ var _internal: String { get throws(JSException) { - return try _$internal_get() + return try _$_internal_get() } } """, - macros: ["JSGetter": JSGetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSSetterMacroTests.swift b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSSetterMacroTests.swift index 83289e092..1ed4e1081 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSSetterMacroTests.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSSetterMacroTests.swift @@ -1,15 +1,18 @@ import SwiftDiagnostics import SwiftSyntax -import SwiftSyntaxMacros -import SwiftSyntaxMacrosTestSupport +import SwiftSyntaxMacroExpansion +import SwiftSyntaxMacrosGenericTestSupport import Testing import BridgeJSMacros @Suite struct JSSetterMacroTests { private let indentationWidth: Trivia = .spaces(4) + private let macroSpecs: [String: MacroSpec] = [ + "JSSetter": MacroSpec(type: JSSetterMacro.self) + ] @Test func topLevelSetter() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSSetter func setFoo(_ value: Foo) throws(JSException) @@ -19,13 +22,13 @@ import BridgeJSMacros try _$foo_set(value) } """, - macros: ["JSSetter": JSSetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func topLevelSetterWithNamedParameter() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSSetter func setCount(count: Int) throws(JSException) @@ -35,13 +38,13 @@ import BridgeJSMacros try _$count_set(count) } """, - macros: ["JSSetter": JSSetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func instanceSetter() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ struct MyClass { @JSSetter @@ -55,13 +58,13 @@ import BridgeJSMacros } } """, - macros: ["JSSetter": JSSetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func staticSetter() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ struct MyClass { @JSSetter @@ -71,17 +74,17 @@ import BridgeJSMacros expandedSource: """ struct MyClass { static func setVersion(_ version: String) throws(JSException) { - try _$version_set(version) + try _$MyClass_version_set(version) } } """, - macros: ["JSSetter": JSSetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func classSetter() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ class MyClass { @JSSetter @@ -91,17 +94,17 @@ import BridgeJSMacros expandedSource: """ class MyClass { class func setConfig(_ config: Config) throws(JSException) { - try _$config_set(config) + try _$MyClass_config_set(config) } } """, - macros: ["JSSetter": JSSetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func enumSetter() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ enum MyEnum { @JSSetter @@ -115,13 +118,13 @@ import BridgeJSMacros } } """, - macros: ["JSSetter": JSSetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func actorSetter() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ actor MyActor { @JSSetter @@ -135,13 +138,13 @@ import BridgeJSMacros } } """, - macros: ["JSSetter": JSSetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func setterWithExistingBody() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSSetter func setFoo(_ value: Foo) throws(JSException) { @@ -153,19 +156,21 @@ import BridgeJSMacros try _$foo_set(value) } """, - macros: ["JSSetter": JSSetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func invalidSetterName() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSSetter func updateFoo(_ value: Foo) throws(JSException) """, expandedSource: """ - func updateFoo(_ value: Foo) throws(JSException) + func updateFoo(_ value: Foo) throws(JSException) { + fatalError("@JSSetter function name must start with 'set' followed by a property name") + } """, diagnostics: [ DiagnosticSpec( @@ -175,19 +180,21 @@ import BridgeJSMacros column: 1 ) ], - macros: ["JSSetter": JSSetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func setterNameTooShort() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSSetter func set(_ value: Foo) throws(JSException) """, expandedSource: """ - func set(_ value: Foo) throws(JSException) + func set(_ value: Foo) throws(JSException) { + fatalError("@JSSetter function name must start with 'set' followed by a property name") + } """, diagnostics: [ DiagnosticSpec( @@ -197,19 +204,21 @@ import BridgeJSMacros column: 1 ) ], - macros: ["JSSetter": JSSetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func setterWithoutParameter() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSSetter func setFoo() throws(JSException) """, expandedSource: """ - func setFoo() throws(JSException) + func setFoo() throws(JSException) { + fatalError("@JSSetter function must have at least one parameter") + } """, diagnostics: [ DiagnosticSpec( @@ -218,13 +227,13 @@ import BridgeJSMacros column: 1 ) ], - macros: ["JSSetter": JSSetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func unsupportedDeclaration() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSSetter var property: String @@ -239,13 +248,13 @@ import BridgeJSMacros column: 1 ) ], - macros: ["JSSetter": JSSetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func setterWithMultipleWords() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSSetter func setConnectionTimeout(_ timeout: Int) throws(JSException) @@ -255,13 +264,13 @@ import BridgeJSMacros try _$connectionTimeout_set(timeout) } """, - macros: ["JSSetter": JSSetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } @Test func setterWithSingleLetterProperty() { - assertMacroExpansion( + TestSupport.assertMacroExpansion( """ @JSSetter func setX(_ x: Int) throws(JSException) @@ -271,8 +280,8 @@ import BridgeJSMacros try _$x_set(x) } """, - macros: ["JSSetter": JSSetterMacro.self], - indentationWidth: indentationWidth + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, ) } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/TestSupport.swift b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/TestSupport.swift new file mode 100644 index 000000000..84e343281 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/TestSupport.swift @@ -0,0 +1,52 @@ +import SwiftSyntaxMacrosGenericTestSupport +import Testing +import SwiftSyntax +import SwiftDiagnostics +import SwiftSyntaxMacroExpansion + +enum TestSupport { + static func failureHandler(spec: TestFailureSpec) { + Issue.record( + Comment(rawValue: spec.message), + sourceLocation: .init( + fileID: spec.location.fileID, + filePath: spec.location.filePath, + line: spec.location.line, + column: spec.location.column + ) + ) + } + + static func assertMacroExpansion( + _ originalSource: String, + expandedSource expectedExpandedSource: String, + diagnostics: [DiagnosticSpec] = [], + macroSpecs: [String: MacroSpec], + applyFixIts: [String]? = nil, + fixedSource expectedFixedSource: String? = nil, + testModuleName: String = "TestModule", + testFileName: String = "test.swift", + indentationWidth: Trivia = .spaces(4), + fileID: StaticString = #fileID, + filePath: StaticString = #filePath, + line: UInt = #line, + column: UInt = #column + ) { + SwiftSyntaxMacrosGenericTestSupport.assertMacroExpansion( + originalSource, + expandedSource: expectedExpandedSource, + diagnostics: diagnostics, + macroSpecs: macroSpecs, + applyFixIts: applyFixIts, + fixedSource: expectedFixedSource, + testModuleName: testModuleName, + testFileName: testFileName, + indentationWidth: indentationWidth, + failureHandler: TestSupport.failureHandler, + fileID: fileID, + filePath: filePath, + line: line, + column: column + ) + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/ImportMacroInputs/GlobalThisImports.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/ImportMacroInputs/GlobalThisImports.swift new file mode 100644 index 000000000..fbf77adf1 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/ImportMacroInputs/GlobalThisImports.swift @@ -0,0 +1,14 @@ +@JSClass +struct JSConsole { + @JSFunction func log(_ message: String) throws(JSException) +} + +@JSGetter(from: .global) var console: JSConsole + +@JSFunction(jsName: "parseInt", from: .global) func parseInt(_ string: String) throws(JSException) -> Double + +@JSClass(from: .global) +struct WebSocket { + @JSFunction init(_ url: String) throws(JSException) + @JSFunction func close() throws(JSException) +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/ImportMacroInputs/SwiftStructImports.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/ImportMacroInputs/SwiftStructImports.swift new file mode 100644 index 000000000..b00fd768a --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/ImportMacroInputs/SwiftStructImports.swift @@ -0,0 +1,7 @@ +@JS +struct Point { + var x: Int + var y: Int +} + +@JSFunction func translate(_ point: Point, dx: Int, dy: Int) throws(JSException) -> Point diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/ArrayTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/ArrayTypes.swift new file mode 100644 index 000000000..8454b7520 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/ArrayTypes.swift @@ -0,0 +1,56 @@ +@JS struct Point { + var x: Double + var y: Double +} + +@JS enum Direction { + case north + case south + case east + case west +} + +@JS enum Status: Int { + case pending = 0 + case active = 1 + case completed = 2 +} + +@JS class Item { + var name: String + + init(name: String) { + self.name = name + } +} + +@JS func processIntArray(_ values: [Int]) -> [Int] +@JS func processStringArray(_ values: [String]) -> [String] +@JS func processDoubleArray(_ values: [Double]) -> [Double] +@JS func processBoolArray(_ values: [Bool]) -> [Bool] + +@JS func processPointArray(_ points: [Point]) -> [Point] + +@JS func processDirectionArray(_ directions: [Direction]) -> [Direction] +@JS func processStatusArray(_ statuses: [Status]) -> [Status] + +@JS func sumIntArray(_ values: [Int]) -> Int +@JS func findFirstPoint(_ points: [Point], matching: String) -> Point + +@JS func processUnsafeRawPointerArray(_ values: [UnsafeRawPointer]) -> [UnsafeRawPointer] +@JS func processUnsafeMutableRawPointerArray(_ values: [UnsafeMutableRawPointer]) -> [UnsafeMutableRawPointer] +@JS func processOpaquePointerArray(_ values: [OpaquePointer]) -> [OpaquePointer] + +@JS func processOptionalIntArray(_ values: [Int?]) -> [Int?] +@JS func processOptionalStringArray(_ values: [String?]) -> [String?] +@JS func processOptionalArray(_ values: [Int]?) -> [Int]? +@JS func processOptionalPointArray(_ points: [Point?]) -> [Point?] +@JS func processOptionalDirectionArray(_ directions: [Direction?]) -> [Direction?] +@JS func processOptionalStatusArray(_ statuses: [Status?]) -> [Status?] + +@JS func processNestedIntArray(_ values: [[Int]]) -> [[Int]] +@JS func processNestedStringArray(_ values: [[String]]) -> [[String]] +@JS func processNestedPointArray(_ points: [[Point]]) -> [[Point]] + +@JS func processItemArray(_ items: [Item]) -> [Item] +@JS func processNestedItemArray(_ items: [[Item]]) -> [[Item]] diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/DefaultParameters.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/DefaultParameters.swift index 73274ad5c..08dcde096 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/DefaultParameters.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/DefaultParameters.swift @@ -73,3 +73,15 @@ @JS func multiply(a: Double, b: Double) -> Double @JS static func subtract(a: Double, b: Double = 5.0) -> Double } + +// Array default values +@JS public func testIntArrayDefault(values: [Int] = [1, 2, 3]) -> [Int] +@JS public func testStringArrayDefault(names: [String] = ["a", "b", "c"]) -> [String] +@JS public func testDoubleArrayDefault(values: [Double] = [1.5, 2.5, 3.5]) -> [Double] +@JS public func testBoolArrayDefault(flags: [Bool] = [true, false, true]) -> [Bool] +@JS public func testEmptyArrayDefault(items: [Int] = []) -> [Int] +@JS public func testMixedWithArrayDefault( + name: String = "test", + values: [Int] = [10, 20, 30], + enabled: Bool = true +) -> String diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/InvalidPropertyNames.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/InvalidPropertyNames.d.ts index d21f3c207..b9d3722b8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/InvalidPropertyNames.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/InvalidPropertyNames.d.ts @@ -21,3 +21,10 @@ interface WeirdNaming { export function createArrayBuffer(): ArrayBufferLike; export function createWeirdObject(): WeirdNaming; + +export class $Weird { + constructor(); + "method-with-dashes"(): void; +} + +export function createWeirdClass(): $Weird; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveParameters.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveParameters.swift index 62e780083..a0d4353eb 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveParameters.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveParameters.swift @@ -1 +1 @@ -@JS func check(a: Int, b: Float, c: Double, d: Bool) {} +@JS func check(a: Int, b: UInt, c: Float, d: Double, e: Bool) {} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveReturn.swift index 96a5dbc3c..144a759ec 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveReturn.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveReturn.swift @@ -1,4 +1,5 @@ @JS func checkInt() -> Int { fatalError() } +@JS func checkUInt() -> UInt { fatalError() } @JS func checkFloat() -> Float { fatalError() } @JS func checkDouble() -> Double { fatalError() } @JS func checkBool() -> Bool { fatalError() } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Protocol.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Protocol.swift index 689f4a355..fbbad0615 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Protocol.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Protocol.swift @@ -96,3 +96,21 @@ import JavaScriptKit delegate.onHelperUpdated(helper) } } + +// Protocol array support +@JS class DelegateManager { + @JS + var delegates: [MyViewControllerDelegate] + + @JS init(delegates: [MyViewControllerDelegate]) { + self.delegates = delegates + } + + @JS func notifyAll() { + for delegate in delegates { + delegate.onSomethingHappened() + } + } +} + +@JS func processDelegates(_ delegates: [MyViewControllerDelegate]) -> [MyViewControllerDelegate] diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/SwiftStruct.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/SwiftStruct.swift index 3415f54a9..ac316a05a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/SwiftStruct.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/SwiftStruct.swift @@ -35,6 +35,17 @@ @JS func roundtrip(_ session: Person) -> Person +@JS enum Precision: Float { + case rough = 0.1 + case fine = 0.001 +} + +@JS struct Measurement { + var value: Double + var precision: Precision + var optionalPrecision: Precision? +} + @JS struct ConfigStruct { @JS static let maxRetries: Int = 3 @JS nonisolated(unsafe) static var defaultConfig: String = "production" diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/UnsafePointer.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/UnsafePointer.swift new file mode 100644 index 000000000..eb6ca0071 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/UnsafePointer.swift @@ -0,0 +1,39 @@ +@JS func takeUnsafeRawPointer(_ p: UnsafeRawPointer) {} +@JS func takeUnsafeMutableRawPointer(_ p: UnsafeMutableRawPointer) {} +@JS func takeOpaquePointer(_ p: OpaquePointer) {} +@JS func takeUnsafePointer(_ p: UnsafePointer) {} +@JS func takeUnsafeMutablePointer(_ p: UnsafeMutablePointer) {} + +@JS func returnUnsafeRawPointer() -> UnsafeRawPointer { UnsafeRawPointer(bitPattern: 1)! } +@JS func returnUnsafeMutableRawPointer() -> UnsafeMutableRawPointer { UnsafeMutableRawPointer(bitPattern: 1)! } +@JS func returnOpaquePointer() -> OpaquePointer { OpaquePointer(bitPattern: 1)! } +@JS func returnUnsafePointer() -> UnsafePointer { + UnsafeRawPointer(bitPattern: 1)!.assumingMemoryBound(to: UInt8.self) +} +@JS func returnUnsafeMutablePointer() -> UnsafeMutablePointer { + UnsafeMutableRawPointer(bitPattern: 1)!.assumingMemoryBound(to: UInt8.self) +} + +@JS struct PointerFields { + var raw: UnsafeRawPointer + var mutRaw: UnsafeMutableRawPointer + var opaque: OpaquePointer + var ptr: UnsafePointer + var mutPtr: UnsafeMutablePointer + + @JS init( + raw: UnsafeRawPointer, + mutRaw: UnsafeMutableRawPointer, + opaque: OpaquePointer, + ptr: UnsafePointer, + mutPtr: UnsafeMutablePointer + ) { + self.raw = raw + self.mutRaw = mutRaw + self.opaque = opaque + self.ptr = ptr + self.mutPtr = mutPtr + } +} + +@JS func roundTripPointerFields(_ value: PointerFields) -> PointerFields { value } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.js index d477487e5..8add18b9f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.Export.d.ts new file mode 100644 index 000000000..988626f3e --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.Export.d.ts @@ -0,0 +1,76 @@ +// 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`. + +export const DirectionValues: { + readonly North: 0; + readonly South: 1; + readonly East: 2; + readonly West: 3; +}; +export type DirectionTag = typeof DirectionValues[keyof typeof DirectionValues]; + +export const StatusValues: { + readonly Pending: 0; + readonly Active: 1; + readonly Completed: 2; +}; +export type StatusTag = typeof StatusValues[keyof typeof StatusValues]; + +export interface Point { + x: number; + y: number; +} +export type DirectionObject = typeof DirectionValues; + +export type StatusObject = typeof StatusValues; + +/// Represents a Swift heap object like a class instance or an actor instance. +export interface SwiftHeapObject { + /// Release the heap object. + /// + /// Note: Calling this method will release the heap object and it will no longer be accessible. + release(): void; +} +export interface Item extends SwiftHeapObject { +} +export type Exports = { + Item: { + } + processIntArray(values: number[]): number[]; + processStringArray(values: string[]): string[]; + processDoubleArray(values: number[]): number[]; + processBoolArray(values: boolean[]): boolean[]; + processPointArray(points: Point[]): Point[]; + processDirectionArray(directions: DirectionTag[]): DirectionTag[]; + processStatusArray(statuses: StatusTag[]): StatusTag[]; + sumIntArray(values: number[]): number; + findFirstPoint(points: Point[], matching: string): Point; + processUnsafeRawPointerArray(values: number[]): number[]; + processUnsafeMutableRawPointerArray(values: number[]): number[]; + processOpaquePointerArray(values: number[]): number[]; + processOptionalIntArray(values: (number | null)[]): (number | null)[]; + processOptionalStringArray(values: (string | null)[]): (string | null)[]; + processOptionalArray(values: number[] | null): number[] | null; + processOptionalPointArray(points: (Point | null)[]): (Point | null)[]; + processOptionalDirectionArray(directions: (DirectionTag | null)[]): (DirectionTag | null)[]; + processOptionalStatusArray(statuses: (StatusTag | null)[]): (StatusTag | null)[]; + processNestedIntArray(values: number[][]): number[][]; + processNestedStringArray(values: string[][]): string[][]; + processNestedPointArray(points: Point[][]): Point[][]; + processItemArray(items: Item[]): Item[]; + processNestedItemArray(items: Item[][]): Item[][]; + Direction: DirectionObject + Status: StatusObject +} +export type Imports = { +} +export function createInstantiator(options: { + imports: Imports; +}, swift: any): Promise<{ + addImports: (importObject: WebAssembly.Imports) => void; + setInstance: (instance: WebAssembly.Instance) => void; + createExports: (instance: WebAssembly.Instance) => Exports; +}>; \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.Export.js new file mode 100644 index 000000000..7388f4150 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.Export.js @@ -0,0 +1,837 @@ +// 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`. + +export const DirectionValues = { + North: 0, + South: 1, + East: 2, + West: 3, +}; + +export const StatusValues = { + Pending: 0, + Active: 1, + Completed: 2, +}; + +export async function createInstantiator(options, swift) { + let instance; + let memory; + let setException; + const textDecoder = new TextDecoder("utf-8"); + const textEncoder = new TextEncoder("utf-8"); + let tmpRetString; + let tmpRetBytes; + let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + let tmpRetPointers = []; + let tmpParamPointers = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createPointHelpers = () => { + return (tmpParamInts, tmpParamF32s, tmpParamF64s, tmpParamPointers, tmpRetPointers, textEncoder, swift, enumHelpers) => ({ + lower: (value) => { + tmpParamF64s.push(value.x); + tmpParamF64s.push(value.y); + return { cleanup: undefined }; + }, + lift: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { + const f64 = tmpRetF64s.pop(); + const f641 = tmpRetF64s.pop(); + return { x: f641, y: f64 }; + } + }); + }; + + return { + /** + * @param {WebAssembly.Imports} importObject + */ + addImports: (importObject, importsContext) => { + bjs = {}; + importObject["bjs"] = bjs; + bjs["swift_js_return_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { + const source = swift.memory.getObject(sourceId); + const bytes = new Uint8Array(memory.buffer, bytesPtr); + bytes.set(source); + } + bjs["swift_js_make_js_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + return swift.memory.retain(textDecoder.decode(bytes)); + } + bjs["swift_js_init_memory_with_result"] = function(ptr, len) { + const target = new Uint8Array(memory.buffer, ptr, len); + target.set(tmpRetBytes); + tmpRetBytes = undefined; + } + bjs["swift_js_throw"] = function(id) { + tmpRetException = swift.memory.retainByRef(id); + } + bjs["swift_js_retain"] = function(id) { + return swift.memory.retainByRef(id); + } + bjs["swift_js_release"] = function(id) { + swift.memory.release(id); + } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_i32"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return tmpParamF64s.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + tmpRetPointers.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return tmpParamPointers.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_struct_lower_Point"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.Point.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_Point"] = function() { + const value = structHelpers.Point.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + return swift.memory.retain(value); + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } else { + tmpRetOptionalBool = value !== 0; + } + } + bjs["swift_js_return_optional_int"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalInt = null; + } else { + tmpRetOptionalInt = value | 0; + } + } + bjs["swift_js_return_optional_float"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalFloat = null; + } else { + tmpRetOptionalFloat = Math.fround(value); + } + } + bjs["swift_js_return_optional_double"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalDouble = null; + } else { + tmpRetOptionalDouble = value; + } + } + bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + if (isSome === 0) { + tmpRetString = null; + } else { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + bjs["swift_js_return_optional_object"] = function(isSome, objectId) { + if (isSome === 0) { + tmpRetString = null; + } else { + tmpRetString = swift.memory.getObject(objectId); + } + } + bjs["swift_js_return_optional_heap_object"] = function(isSome, pointer) { + if (isSome === 0) { + tmpRetOptionalHeapObject = null; + } else { + tmpRetOptionalHeapObject = pointer; + } + } + bjs["swift_js_get_optional_int_presence"] = function() { + return tmpRetOptionalInt != null ? 1 : 0; + } + bjs["swift_js_get_optional_int_value"] = function() { + const value = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return value; + } + bjs["swift_js_get_optional_string"] = function() { + const str = tmpRetString; + tmpRetString = undefined; + if (str == null) { + return -1; + } else { + const bytes = textEncoder.encode(str); + tmpRetBytes = bytes; + return bytes.length; + } + } + bjs["swift_js_get_optional_float_presence"] = function() { + return tmpRetOptionalFloat != null ? 1 : 0; + } + bjs["swift_js_get_optional_float_value"] = function() { + const value = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; + return value; + } + bjs["swift_js_get_optional_double_presence"] = function() { + return tmpRetOptionalDouble != null ? 1 : 0; + } + bjs["swift_js_get_optional_double_value"] = function() { + const value = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + return value; + } + bjs["swift_js_get_optional_heap_object_pointer"] = function() { + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + return pointer || 0; + } + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_Item_wrap"] = function(pointer) { + const obj = Item.__construct(pointer); + return swift.memory.retain(obj); + }; + }, + setInstance: (i) => { + instance = i; + memory = instance.exports.memory; + + setException = (error) => { + instance.exports._swift_js_exception.value = swift.memory.retain(error) + } + }, + /** @param {WebAssembly.Instance} instance */ + createExports: (instance) => { + const js = swift.memory.heap; + /// Represents a Swift heap object like a class instance or an actor instance. + class SwiftHeapObject { + static __wrap(pointer, deinit, prototype) { + const obj = Object.create(prototype); + obj.pointer = pointer; + obj.hasReleased = false; + obj.deinit = deinit; + obj.registry = new FinalizationRegistry((pointer) => { + deinit(pointer); + }); + obj.registry.register(this, obj.pointer); + return obj; + } + + release() { + this.registry.unregister(this); + this.deinit(this.pointer); + } + } + class Item extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Item_deinit, Item.prototype); + } + + } + const PointHelpers = __bjs_createPointHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, tmpParamPointers, tmpRetPointers, textEncoder, swift, enumHelpers); + structHelpers.Point = PointHelpers; + + const exports = { + Item, + processIntArray: function bjs_processIntArray(values) { + const arrayCleanups = []; + for (const elem of values) { + tmpParamInts.push((elem | 0)); + } + tmpParamInts.push(values.length); + instance.exports.bjs_processIntArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = tmpRetInts.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processStringArray: function bjs_processStringArray(values) { + const arrayCleanups = []; + for (const elem of values) { + const bytes = textEncoder.encode(elem); + const id = swift.memory.retain(bytes); + tmpParamInts.push(bytes.length); + tmpParamInts.push(id); + arrayCleanups.push(() => { + swift.memory.release(id); + }); + } + tmpParamInts.push(values.length); + instance.exports.bjs_processStringArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const string = tmpRetStrings.pop(); + arrayResult.push(string); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processDoubleArray: function bjs_processDoubleArray(values) { + const arrayCleanups = []; + for (const elem of values) { + tmpParamF64s.push(elem); + } + tmpParamInts.push(values.length); + instance.exports.bjs_processDoubleArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const f64 = tmpRetF64s.pop(); + arrayResult.push(f64); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processBoolArray: function bjs_processBoolArray(values) { + const arrayCleanups = []; + for (const elem of values) { + tmpParamInts.push(elem ? 1 : 0); + } + tmpParamInts.push(values.length); + instance.exports.bjs_processBoolArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const bool = tmpRetInts.pop() !== 0; + arrayResult.push(bool); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processPointArray: function bjs_processPointArray(points) { + const arrayCleanups = []; + for (const elem of points) { + const { cleanup: cleanup } = structHelpers.Point.lower(elem); + arrayCleanups.push(() => { + if (cleanup) { cleanup(); } + }); + } + tmpParamInts.push(points.length); + instance.exports.bjs_processPointArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const struct = structHelpers.Point.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + arrayResult.push(struct); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processDirectionArray: function bjs_processDirectionArray(directions) { + const arrayCleanups = []; + for (const elem of directions) { + tmpParamInts.push((elem | 0)); + } + tmpParamInts.push(directions.length); + instance.exports.bjs_processDirectionArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const caseId = tmpRetInts.pop(); + arrayResult.push(caseId); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processStatusArray: function bjs_processStatusArray(statuses) { + const arrayCleanups = []; + for (const elem of statuses) { + tmpParamInts.push((elem | 0)); + } + tmpParamInts.push(statuses.length); + instance.exports.bjs_processStatusArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const rawValue = tmpRetInts.pop(); + arrayResult.push(rawValue); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + sumIntArray: function bjs_sumIntArray(values) { + const arrayCleanups = []; + for (const elem of values) { + tmpParamInts.push((elem | 0)); + } + tmpParamInts.push(values.length); + const ret = instance.exports.bjs_sumIntArray(); + for (const cleanup of arrayCleanups) { cleanup(); } + return ret; + }, + findFirstPoint: function bjs_findFirstPoint(points, matching) { + const arrayCleanups = []; + for (const elem of points) { + const { cleanup: cleanup } = structHelpers.Point.lower(elem); + arrayCleanups.push(() => { + if (cleanup) { cleanup(); } + }); + } + tmpParamInts.push(points.length); + const matchingBytes = textEncoder.encode(matching); + const matchingId = swift.memory.retain(matchingBytes); + instance.exports.bjs_findFirstPoint(matchingId, matchingBytes.length); + const structValue = structHelpers.Point.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + for (const cleanup of arrayCleanups) { cleanup(); } + swift.memory.release(matchingId); + return structValue; + }, + processUnsafeRawPointerArray: function bjs_processUnsafeRawPointerArray(values) { + const arrayCleanups = []; + for (const elem of values) { + tmpParamPointers.push((elem | 0)); + } + tmpParamInts.push(values.length); + instance.exports.bjs_processUnsafeRawPointerArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const pointer = tmpRetPointers.pop(); + arrayResult.push(pointer); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processUnsafeMutableRawPointerArray: function bjs_processUnsafeMutableRawPointerArray(values) { + const arrayCleanups = []; + for (const elem of values) { + tmpParamPointers.push((elem | 0)); + } + tmpParamInts.push(values.length); + instance.exports.bjs_processUnsafeMutableRawPointerArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const pointer = tmpRetPointers.pop(); + arrayResult.push(pointer); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processOpaquePointerArray: function bjs_processOpaquePointerArray(values) { + const arrayCleanups = []; + for (const elem of values) { + tmpParamPointers.push((elem | 0)); + } + tmpParamInts.push(values.length); + instance.exports.bjs_processOpaquePointerArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const pointer = tmpRetPointers.pop(); + arrayResult.push(pointer); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processOptionalIntArray: function bjs_processOptionalIntArray(values) { + const arrayCleanups = []; + for (const elem of values) { + const isSome = elem != null ? 1 : 0; + if (isSome) { + tmpParamInts.push((elem | 0)); + } else { + tmpParamInts.push(0); + } + tmpParamInts.push(isSome); + } + tmpParamInts.push(values.length); + instance.exports.bjs_processOptionalIntArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const isSome1 = tmpRetInts.pop(); + let optValue; + if (isSome1 === 0) { + optValue = null; + } else { + const int = tmpRetInts.pop(); + optValue = int; + } + arrayResult.push(optValue); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processOptionalStringArray: function bjs_processOptionalStringArray(values) { + const arrayCleanups = []; + for (const elem of values) { + const isSome = elem != null ? 1 : 0; + if (isSome) { + const bytes = textEncoder.encode(elem); + const id = swift.memory.retain(bytes); + tmpParamInts.push(bytes.length); + tmpParamInts.push(id); + arrayCleanups.push(() => { swift.memory.release(id); }); + } else { + tmpParamInts.push(0); + tmpParamInts.push(0); + } + tmpParamInts.push(isSome); + } + tmpParamInts.push(values.length); + instance.exports.bjs_processOptionalStringArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const isSome1 = tmpRetInts.pop(); + let optValue; + if (isSome1 === 0) { + optValue = null; + } else { + const string = tmpRetStrings.pop(); + optValue = string; + } + arrayResult.push(optValue); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processOptionalArray: function bjs_processOptionalArray(values) { + const isSome = values != null; + const valuesCleanups = []; + if (isSome) { + const arrayCleanups = []; + for (const elem of values) { + tmpParamInts.push((elem | 0)); + } + tmpParamInts.push(values.length); + valuesCleanups.push(() => { for (const cleanup of arrayCleanups) { cleanup(); } }); + } + instance.exports.bjs_processOptionalArray(+isSome); + const isSome1 = tmpRetInts.pop(); + let optResult; + if (isSome1) { + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = tmpRetInts.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); + optResult = arrayResult; + } else { + optResult = null; + } + for (const cleanup of valuesCleanups) { cleanup(); } + return optResult; + }, + processOptionalPointArray: function bjs_processOptionalPointArray(points) { + const arrayCleanups = []; + for (const elem of points) { + const isSome = elem != null ? 1 : 0; + if (isSome) { + const { cleanup: cleanup } = structHelpers.Point.lower(elem); + arrayCleanups.push(() => { if (cleanup) { cleanup(); } }); + } else { + } + tmpParamInts.push(isSome); + } + tmpParamInts.push(points.length); + instance.exports.bjs_processOptionalPointArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const isSome1 = tmpRetInts.pop(); + let optValue; + if (isSome1 === 0) { + optValue = null; + } else { + const struct = structHelpers.Point.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + optValue = struct; + } + arrayResult.push(optValue); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processOptionalDirectionArray: function bjs_processOptionalDirectionArray(directions) { + const arrayCleanups = []; + for (const elem of directions) { + const isSome = elem != null ? 1 : 0; + if (isSome) { + tmpParamInts.push((elem | 0)); + } else { + tmpParamInts.push(0); + } + tmpParamInts.push(isSome); + } + tmpParamInts.push(directions.length); + instance.exports.bjs_processOptionalDirectionArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const isSome1 = tmpRetInts.pop(); + let optValue; + if (isSome1 === 0) { + optValue = null; + } else { + const caseId = tmpRetInts.pop(); + optValue = caseId; + } + arrayResult.push(optValue); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processOptionalStatusArray: function bjs_processOptionalStatusArray(statuses) { + const arrayCleanups = []; + for (const elem of statuses) { + const isSome = elem != null ? 1 : 0; + if (isSome) { + tmpParamInts.push((elem | 0)); + } else { + tmpParamInts.push(0); + } + tmpParamInts.push(isSome); + } + tmpParamInts.push(statuses.length); + instance.exports.bjs_processOptionalStatusArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const isSome1 = tmpRetInts.pop(); + let optValue; + if (isSome1 === 0) { + optValue = null; + } else { + const rawValue = tmpRetInts.pop(); + optValue = rawValue; + } + arrayResult.push(optValue); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processNestedIntArray: function bjs_processNestedIntArray(values) { + const arrayCleanups = []; + for (const elem of values) { + const arrayCleanups1 = []; + for (const elem1 of elem) { + tmpParamInts.push((elem1 | 0)); + } + tmpParamInts.push(elem.length); + arrayCleanups.push(() => { + for (const cleanup of arrayCleanups1) { cleanup(); } + }); + } + tmpParamInts.push(values.length); + instance.exports.bjs_processNestedIntArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const arrayLen1 = tmpRetInts.pop(); + const arrayResult1 = []; + for (let i1 = 0; i1 < arrayLen1; i1++) { + const int = tmpRetInts.pop(); + arrayResult1.push(int); + } + arrayResult1.reverse(); + arrayResult.push(arrayResult1); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processNestedStringArray: function bjs_processNestedStringArray(values) { + const arrayCleanups = []; + for (const elem of values) { + const arrayCleanups1 = []; + for (const elem1 of elem) { + const bytes = textEncoder.encode(elem1); + const id = swift.memory.retain(bytes); + tmpParamInts.push(bytes.length); + tmpParamInts.push(id); + arrayCleanups1.push(() => { + swift.memory.release(id); + }); + } + tmpParamInts.push(elem.length); + arrayCleanups.push(() => { + for (const cleanup of arrayCleanups1) { cleanup(); } + }); + } + tmpParamInts.push(values.length); + instance.exports.bjs_processNestedStringArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const arrayLen1 = tmpRetInts.pop(); + const arrayResult1 = []; + for (let i1 = 0; i1 < arrayLen1; i1++) { + const string = tmpRetStrings.pop(); + arrayResult1.push(string); + } + arrayResult1.reverse(); + arrayResult.push(arrayResult1); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processNestedPointArray: function bjs_processNestedPointArray(points) { + const arrayCleanups = []; + for (const elem of points) { + const arrayCleanups1 = []; + for (const elem1 of elem) { + const { cleanup: cleanup } = structHelpers.Point.lower(elem1); + arrayCleanups1.push(() => { + if (cleanup) { cleanup(); } + }); + } + tmpParamInts.push(elem.length); + arrayCleanups.push(() => { + for (const cleanup of arrayCleanups1) { cleanup(); } + }); + } + tmpParamInts.push(points.length); + instance.exports.bjs_processNestedPointArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const arrayLen1 = tmpRetInts.pop(); + const arrayResult1 = []; + for (let i1 = 0; i1 < arrayLen1; i1++) { + const struct = structHelpers.Point.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + arrayResult1.push(struct); + } + arrayResult1.reverse(); + arrayResult.push(arrayResult1); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processItemArray: function bjs_processItemArray(items) { + const arrayCleanups = []; + for (const elem of items) { + tmpParamPointers.push(elem.pointer); + } + tmpParamInts.push(items.length); + instance.exports.bjs_processItemArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const ptr = tmpRetPointers.pop(); + const obj = Item.__construct(ptr); + arrayResult.push(obj); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processNestedItemArray: function bjs_processNestedItemArray(items) { + const arrayCleanups = []; + for (const elem of items) { + const arrayCleanups1 = []; + for (const elem1 of elem) { + tmpParamPointers.push(elem1.pointer); + } + tmpParamInts.push(elem.length); + arrayCleanups.push(() => { + for (const cleanup of arrayCleanups1) { cleanup(); } + }); + } + tmpParamInts.push(items.length); + instance.exports.bjs_processNestedItemArray(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const arrayLen1 = tmpRetInts.pop(); + const arrayResult1 = []; + for (let i1 = 0; i1 < arrayLen1; i1++) { + const ptr = tmpRetPointers.pop(); + const obj = Item.__construct(ptr); + arrayResult1.push(obj); + } + arrayResult1.reverse(); + arrayResult.push(arrayResult1); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + Direction: DirectionValues, + Status: StatusValues, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js index c01eac976..4015b6261 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -71,7 +72,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -85,21 +86,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js index 15b2a9742..981cecbe5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.Export.d.ts index c024ecfb6..ac5658eb3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.Export.d.ts @@ -116,6 +116,32 @@ export type Exports = { * @param point - Optional parameter (default: { name: "default", value: 42, enabled: true }) */ testOptionalStructWithValueDefault(point?: Config | null): Config | null; + /** + * @param values - Optional parameter (default: [1, 2, 3]) + */ + testIntArrayDefault(values?: number[]): number[]; + /** + * @param names - Optional parameter (default: ["a", "b", "c"]) + */ + testStringArrayDefault(names?: string[]): string[]; + /** + * @param values - Optional parameter (default: [1.5, 2.5, 3.5]) + */ + testDoubleArrayDefault(values?: number[]): number[]; + /** + * @param flags - Optional parameter (default: [true, false, true]) + */ + testBoolArrayDefault(flags?: boolean[]): boolean[]; + /** + * @param items - Optional parameter (default: []) + */ + testEmptyArrayDefault(items?: number[]): number[]; + /** + * @param name - Optional parameter (default: "test") + * @param values - Optional parameter (default: [10, 20, 30]) + * @param enabled - Optional parameter (default: true) + */ + testMixedWithArrayDefault(name?: string, values?: number[], enabled?: boolean): string; Status: StatusObject MathOperations: { /** diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.Export.js index 48dfc0994..978272568 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.Export.js @@ -34,6 +34,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -53,7 +54,7 @@ export async function createInstantiator(options, swift) { }; return { cleanup }; }, - raise: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { + lift: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { const bool = tmpRetInts.pop() !== 0; const int = tmpRetInts.pop(); const string = tmpRetStrings.pop(); @@ -67,7 +68,7 @@ export async function createInstantiator(options, swift) { tmpParamF64s.push(value.baseValue); return { cleanup: undefined }; }, - raise: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { + lift: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { const f64 = tmpRetF64s.pop(); const instance1 = { baseValue: f64 }; instance1.add = function(a, b = 10.0) { @@ -124,7 +125,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -138,21 +139,53 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_struct_lower_Config"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.Config.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_Config"] = function() { + const value = structHelpers.Config.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_MathOperations"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.MathOperations.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_MathOperations"] = function() { + const value = structHelpers.MathOperations.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + return swift.memory.retain(value); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -495,7 +528,7 @@ export async function createInstantiator(options, swift) { const isSome1 = tmpRetInts.pop(); let optResult; if (isSome1) { - optResult = structHelpers.Config.raise(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + optResult = structHelpers.Config.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); } else { optResult = null; } @@ -513,18 +546,124 @@ export async function createInstantiator(options, swift) { const isSome1 = tmpRetInts.pop(); let optResult; if (isSome1) { - optResult = structHelpers.Config.raise(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + optResult = structHelpers.Config.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); } else { optResult = null; } if (pointCleanup) { pointCleanup(); } return optResult; }, + testIntArrayDefault: function bjs_testIntArrayDefault(values = [1, 2, 3]) { + const arrayCleanups = []; + for (const elem of values) { + tmpParamInts.push((elem | 0)); + } + tmpParamInts.push(values.length); + instance.exports.bjs_testIntArrayDefault(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = tmpRetInts.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + testStringArrayDefault: function bjs_testStringArrayDefault(names = ["a", "b", "c"]) { + const arrayCleanups = []; + for (const elem of names) { + const bytes = textEncoder.encode(elem); + const id = swift.memory.retain(bytes); + tmpParamInts.push(bytes.length); + tmpParamInts.push(id); + arrayCleanups.push(() => { + swift.memory.release(id); + }); + } + tmpParamInts.push(names.length); + instance.exports.bjs_testStringArrayDefault(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const string = tmpRetStrings.pop(); + arrayResult.push(string); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + testDoubleArrayDefault: function bjs_testDoubleArrayDefault(values = [1.5, 2.5, 3.5]) { + const arrayCleanups = []; + for (const elem of values) { + tmpParamF64s.push(elem); + } + tmpParamInts.push(values.length); + instance.exports.bjs_testDoubleArrayDefault(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const f64 = tmpRetF64s.pop(); + arrayResult.push(f64); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + testBoolArrayDefault: function bjs_testBoolArrayDefault(flags = [true, false, true]) { + const arrayCleanups = []; + for (const elem of flags) { + tmpParamInts.push(elem ? 1 : 0); + } + tmpParamInts.push(flags.length); + instance.exports.bjs_testBoolArrayDefault(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const bool = tmpRetInts.pop() !== 0; + arrayResult.push(bool); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + testEmptyArrayDefault: function bjs_testEmptyArrayDefault(items = []) { + const arrayCleanups = []; + for (const elem of items) { + tmpParamInts.push((elem | 0)); + } + tmpParamInts.push(items.length); + instance.exports.bjs_testEmptyArrayDefault(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = tmpRetInts.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + testMixedWithArrayDefault: function bjs_testMixedWithArrayDefault(name = "test", values = [10, 20, 30], enabled = true) { + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + const arrayCleanups = []; + for (const elem of values) { + tmpParamInts.push((elem | 0)); + } + tmpParamInts.push(values.length); + instance.exports.bjs_testMixedWithArrayDefault(nameId, nameBytes.length, enabled); + const ret = tmpRetString; + tmpRetString = undefined; + swift.memory.release(nameId); + for (const cleanup of arrayCleanups) { cleanup(); } + return ret; + }, Status: StatusValues, MathOperations: { init: function(baseValue = 0.0) { instance.exports.bjs_MathOperations_init(baseValue); - const structValue = structHelpers.MathOperations.raise(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + const structValue = structHelpers.MathOperations.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); return structValue; }, subtract: function(a, b) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.js index a15e386e8..2d8dbc0ca 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.js @@ -57,7 +57,7 @@ const __bjs_createAPIResultValuesHelpers = () => { default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); } }, - raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { + lift: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { const tag = tmpRetTag | 0; switch (tag) { case APIResultValues.Tag.Success: { @@ -175,7 +175,7 @@ const __bjs_createComplexResultValuesHelpers = () => { default: throw new Error("Unknown ComplexResultValues tag: " + String(enumTag)); } }, - raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { + lift: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { const tag = tmpRetTag | 0; switch (tag) { case ComplexResultValues.Tag.Success: { @@ -266,7 +266,7 @@ const __bjs_createResultValuesHelpers = () => { default: throw new Error("Unknown ResultValues tag: " + String(enumTag)); } }, - raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { + lift: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { const tag = tmpRetTag | 0; switch (tag) { case ResultValues.Tag.Success: { @@ -325,7 +325,7 @@ const __bjs_createNetworkingResultValuesHelpers = () => { default: throw new Error("Unknown NetworkingResultValues tag: " + String(enumTag)); } }, - raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { + lift: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { const tag = tmpRetTag | 0; switch (tag) { case NetworkingResultValues.Tag.Success: { @@ -414,7 +414,7 @@ const __bjs_createAPIOptionalResultValuesHelpers = () => { default: throw new Error("Unknown APIOptionalResultValues tag: " + String(enumTag)); } }, - raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { + lift: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { const tag = tmpRetTag | 0; switch (tag) { case APIOptionalResultValues.Tag.Success: { @@ -503,6 +503,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -546,7 +547,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -560,21 +561,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -700,13 +711,13 @@ export async function createInstantiator(options, swift) { }, getResult: function bjs_getResult() { instance.exports.bjs_getResult(); - const ret = enumHelpers.APIResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + const ret = enumHelpers.APIResult.lift(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); 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.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + const ret = enumHelpers.APIResult.lift(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); if (resultCleanup) { resultCleanup(); } return ret; }, @@ -724,7 +735,7 @@ export async function createInstantiator(options, swift) { if (isNull) { optResult = null; } else { - optResult = enumHelpers.APIResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + optResult = enumHelpers.APIResult.lift(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); } if (resultCleanup) { resultCleanup(); } return optResult; @@ -736,13 +747,13 @@ export async function createInstantiator(options, swift) { }, getComplexResult: function bjs_getComplexResult() { instance.exports.bjs_getComplexResult(); - const ret = enumHelpers.ComplexResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + const ret = enumHelpers.ComplexResult.lift(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); 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.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + const ret = enumHelpers.ComplexResult.lift(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); if (resultCleanup) { resultCleanup(); } return ret; }, @@ -760,7 +771,7 @@ export async function createInstantiator(options, swift) { if (isNull) { optResult = null; } else { - optResult = enumHelpers.ComplexResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + optResult = enumHelpers.ComplexResult.lift(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); } if (resultCleanup) { resultCleanup(); } return optResult; @@ -779,7 +790,7 @@ export async function createInstantiator(options, swift) { if (isNull) { optResult = null; } else { - optResult = enumHelpers.Result.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + optResult = enumHelpers.Result.lift(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); } if (resultCleanup) { resultCleanup(); } return optResult; @@ -798,7 +809,7 @@ export async function createInstantiator(options, swift) { if (isNull) { optResult = null; } else { - optResult = enumHelpers.NetworkingResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + optResult = enumHelpers.NetworkingResult.lift(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); } if (resultCleanup) { resultCleanup(); } return optResult; @@ -817,7 +828,7 @@ export async function createInstantiator(options, swift) { if (isNull) { optResult = null; } else { - optResult = enumHelpers.APIOptionalResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + optResult = enumHelpers.APIOptionalResult.lift(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); } if (resultCleanup) { resultCleanup(); } return optResult; @@ -843,7 +854,7 @@ export async function createInstantiator(options, swift) { if (isNull) { optResult = null; } else { - optResult = enumHelpers.APIOptionalResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + optResult = enumHelpers.APIOptionalResult.lift(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); } if (result1Cleanup) { result1Cleanup(); } if (result2Cleanup) { result2Cleanup(); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js index 9cd3e1f3b..89a0f0897 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js @@ -52,6 +52,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -95,7 +96,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -109,21 +110,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js index 34a2e0540..b01148873 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js @@ -53,6 +53,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -96,7 +97,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -110,21 +111,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.Export.js index 074380d00..77c327e8d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.Export.js @@ -72,6 +72,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -115,7 +116,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -129,21 +130,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js index 00b542e30..c1865adfc 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js @@ -103,6 +103,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -146,7 +147,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -160,21 +161,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.ImportMacros.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.ImportMacros.js index 89aa3af9d..b3b809476 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.ImportMacros.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.ImportMacros.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -194,7 +205,7 @@ export async function createInstantiator(options, swift) { const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_console_get"] = function bjs_console_get() { try { - let ret = imports["console"]; + let ret = imports.console; return swift.memory.retain(ret); } catch (error) { setException(error); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.ImportMacros.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.ImportMacros.d.ts new file mode 100644 index 000000000..ae1152016 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.ImportMacros.d.ts @@ -0,0 +1,23 @@ +// 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`. + +export interface JSConsole { + log(message: string): void; +} +export interface WebSocket { + close(): void; +} +export type Exports = { +} +export type Imports = { +} +export function createInstantiator(options: { + imports: Imports; +}, swift: any): Promise<{ + addImports: (importObject: WebAssembly.Imports) => void; + setInstance: (instance: WebAssembly.Instance) => void; + createExports: (instance: WebAssembly.Instance) => Exports; +}>; \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.ImportMacros.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.ImportMacros.js new file mode 100644 index 000000000..35a3d76ec --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.ImportMacros.js @@ -0,0 +1,269 @@ +// 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`. + +export async function createInstantiator(options, swift) { + let instance; + let memory; + let setException; + const textDecoder = new TextDecoder("utf-8"); + const textEncoder = new TextEncoder("utf-8"); + let tmpRetString; + let tmpRetBytes; + let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + let tmpRetPointers = []; + let tmpParamPointers = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + + return { + /** + * @param {WebAssembly.Imports} importObject + */ + addImports: (importObject, importsContext) => { + bjs = {}; + importObject["bjs"] = bjs; + bjs["swift_js_return_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { + const source = swift.memory.getObject(sourceId); + const bytes = new Uint8Array(memory.buffer, bytesPtr); + bytes.set(source); + } + bjs["swift_js_make_js_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + return swift.memory.retain(textDecoder.decode(bytes)); + } + bjs["swift_js_init_memory_with_result"] = function(ptr, len) { + const target = new Uint8Array(memory.buffer, ptr, len); + target.set(tmpRetBytes); + tmpRetBytes = undefined; + } + bjs["swift_js_throw"] = function(id) { + tmpRetException = swift.memory.retainByRef(id); + } + bjs["swift_js_retain"] = function(id) { + return swift.memory.retainByRef(id); + } + bjs["swift_js_release"] = function(id) { + swift.memory.release(id); + } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_i32"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return tmpParamF64s.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + tmpRetPointers.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return tmpParamPointers.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } else { + tmpRetOptionalBool = value !== 0; + } + } + bjs["swift_js_return_optional_int"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalInt = null; + } else { + tmpRetOptionalInt = value | 0; + } + } + bjs["swift_js_return_optional_float"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalFloat = null; + } else { + tmpRetOptionalFloat = Math.fround(value); + } + } + bjs["swift_js_return_optional_double"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalDouble = null; + } else { + tmpRetOptionalDouble = value; + } + } + bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + if (isSome === 0) { + tmpRetString = null; + } else { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + bjs["swift_js_return_optional_object"] = function(isSome, objectId) { + if (isSome === 0) { + tmpRetString = null; + } else { + tmpRetString = swift.memory.getObject(objectId); + } + } + bjs["swift_js_return_optional_heap_object"] = function(isSome, pointer) { + if (isSome === 0) { + tmpRetOptionalHeapObject = null; + } else { + tmpRetOptionalHeapObject = pointer; + } + } + bjs["swift_js_get_optional_int_presence"] = function() { + return tmpRetOptionalInt != null ? 1 : 0; + } + bjs["swift_js_get_optional_int_value"] = function() { + const value = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return value; + } + bjs["swift_js_get_optional_string"] = function() { + const str = tmpRetString; + tmpRetString = undefined; + if (str == null) { + return -1; + } else { + const bytes = textEncoder.encode(str); + tmpRetBytes = bytes; + return bytes.length; + } + } + bjs["swift_js_get_optional_float_presence"] = function() { + return tmpRetOptionalFloat != null ? 1 : 0; + } + bjs["swift_js_get_optional_float_value"] = function() { + const value = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; + return value; + } + bjs["swift_js_get_optional_double_presence"] = function() { + return tmpRetOptionalDouble != null ? 1 : 0; + } + bjs["swift_js_get_optional_double_value"] = function() { + const value = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + return value; + } + bjs["swift_js_get_optional_heap_object_pointer"] = function() { + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + return pointer || 0; + } + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_console_get"] = function bjs_console_get() { + try { + let ret = globalThis.console; + return swift.memory.retain(ret); + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_parseInt"] = function bjs_parseInt(string) { + try { + const stringObject = swift.memory.getObject(string); + swift.memory.release(string); + let ret = globalThis.parseInt(stringObject); + return ret; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_JSConsole_log"] = function bjs_JSConsole_log(self, message) { + try { + const messageObject = swift.memory.getObject(message); + swift.memory.release(message); + swift.memory.getObject(self).log(messageObject); + } catch (error) { + setException(error); + } + } + TestModule["bjs_WebSocket_init"] = function bjs_WebSocket_init(url) { + try { + const urlObject = swift.memory.getObject(url); + swift.memory.release(url); + return swift.memory.retain(new globalThis.WebSocket(urlObject)); + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_WebSocket_close"] = function bjs_WebSocket_close(self) { + try { + swift.memory.getObject(self).close(); + } catch (error) { + setException(error); + } + } + }, + setInstance: (i) => { + instance = i; + memory = instance.exports.memory; + + setException = (error) => { + instance.exports._swift_js_exception.value = swift.memory.retain(error) + } + }, + /** @param {WebAssembly.Instance} instance */ + createExports: (instance) => { + const js = swift.memory.heap; + const exports = { + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.Export.js index 93c23a0db..094c2241d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.Export.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.js index 83450b4c5..1d25a2954 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.Import.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.Import.d.ts index 2b0474bb5..2efd24317 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.Import.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.Import.d.ts @@ -10,15 +10,28 @@ export interface ArrayBufferLike { } export interface WeirdNaming { as(): void; + try(): void; normalProperty: string; + "property-with-dashes": number; + "123invalidStart": boolean; + "property with spaces": string; + "@specialChar": number; + constructor: string; for: string; Any: string; } +export interface _Weird { + "method-with-dashes"(): void; +} export type Exports = { } export type Imports = { createArrayBuffer(): ArrayBufferLike; createWeirdObject(): WeirdNaming; + createWeirdClass(): _Weird; + _Weird: { + new(): _Weird; + } } export function createInstantiator(options: { imports: Imports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.Import.js index 60435e569..833436226 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.Import.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -210,6 +221,15 @@ export async function createInstantiator(options, swift) { return 0 } } + TestModule["bjs_createWeirdClass"] = function bjs_createWeirdClass() { + try { + let ret = imports.createWeirdClass(); + return swift.memory.retain(ret); + } catch (error) { + setException(error); + return 0 + } + } TestModule["bjs_ArrayBufferLike_byteLength_get"] = function bjs_ArrayBufferLike_byteLength_get(self) { try { let ret = swift.memory.getObject(self).byteLength; @@ -237,6 +257,51 @@ export async function createInstantiator(options, swift) { setException(error); } } + TestModule["bjs_WeirdNaming_property_with_dashes_get"] = function bjs_WeirdNaming_property_with_dashes_get(self) { + try { + let ret = swift.memory.getObject(self)["property-with-dashes"]; + return ret; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_WeirdNaming__123invalidStart_get"] = function bjs_WeirdNaming__123invalidStart_get(self) { + try { + let ret = swift.memory.getObject(self)["123invalidStart"]; + return ret ? 1 : 0; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_WeirdNaming_property_with_spaces_get"] = function bjs_WeirdNaming_property_with_spaces_get(self) { + try { + let ret = swift.memory.getObject(self)["property with spaces"]; + tmpRetBytes = textEncoder.encode(ret); + return tmpRetBytes.length; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WeirdNaming__specialChar_get"] = function bjs_WeirdNaming__specialChar_get(self) { + try { + let ret = swift.memory.getObject(self)["@specialChar"]; + return ret; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_WeirdNaming_constructor_get"] = function bjs_WeirdNaming_constructor_get(self) { + try { + let ret = swift.memory.getObject(self).constructor; + tmpRetBytes = textEncoder.encode(ret); + return tmpRetBytes.length; + } catch (error) { + setException(error); + } + } TestModule["bjs_WeirdNaming_for_get"] = function bjs_WeirdNaming_for_get(self) { try { let ret = swift.memory.getObject(self).for; @@ -264,6 +329,45 @@ export async function createInstantiator(options, swift) { setException(error); } } + TestModule["bjs_WeirdNaming_property_with_dashes_set"] = function bjs_WeirdNaming_property_with_dashes_set(self, newValue) { + try { + swift.memory.getObject(self)["property-with-dashes"] = newValue; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WeirdNaming__123invalidStart_set"] = function bjs_WeirdNaming__123invalidStart_set(self, newValue) { + try { + swift.memory.getObject(self)["123invalidStart"] = newValue !== 0; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WeirdNaming_property_with_spaces_set"] = function bjs_WeirdNaming_property_with_spaces_set(self, newValue) { + try { + const newValueObject = swift.memory.getObject(newValue); + swift.memory.release(newValue); + swift.memory.getObject(self)["property with spaces"] = newValueObject; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WeirdNaming__specialChar_set"] = function bjs_WeirdNaming__specialChar_set(self, newValue) { + try { + swift.memory.getObject(self)["@specialChar"] = newValue; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WeirdNaming_constructor_set"] = function bjs_WeirdNaming_constructor_set(self, newValue) { + try { + const newValueObject = swift.memory.getObject(newValue); + swift.memory.release(newValue); + swift.memory.getObject(self).constructor = newValueObject; + } catch (error) { + setException(error); + } + } TestModule["bjs_WeirdNaming_for_set"] = function bjs_WeirdNaming_for_set(self, newValue) { try { const newValueObject = swift.memory.getObject(newValue); @@ -289,6 +393,28 @@ export async function createInstantiator(options, swift) { setException(error); } } + TestModule["bjs_WeirdNaming_try"] = function bjs_WeirdNaming_try(self) { + try { + swift.memory.getObject(self).try(); + } catch (error) { + setException(error); + } + } + TestModule["bjs__Weird_init"] = function bjs__Weird_init() { + try { + return swift.memory.retain(new imports.$Weird()); + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs__Weird_method_with_dashes"] = function bjs__Weird_method_with_dashes(self) { + try { + swift.memory.getObject(self)["method-with-dashes"](); + } catch (error) { + setException(error); + } + } }, setInstance: (i) => { instance = i; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.Export.js index ce9475b0c..f079de1da 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.Export.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -71,7 +72,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -85,21 +86,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.Export.js index c4a1c2e3a..2c43b91e8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.Export.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -71,7 +72,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -85,21 +86,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.Export.js index d0f00f279..4b8ce8a66 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.Export.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -71,7 +72,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -85,21 +86,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js index 40a3f4e3f..f8cfd7366 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js index 0b6ef40dc..ae7bf7451 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -71,7 +72,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -85,21 +86,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.Export.js index 6b4d37fc5..671868eab 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.Export.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -71,7 +72,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -85,21 +86,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.Export.js index 9770da2db..2c08e3d9f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.Export.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -71,7 +72,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -85,21 +86,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.d.ts index a9c37f378..9bf0e1e35 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.d.ts @@ -5,7 +5,7 @@ // `swift package bridge-js`. export type Exports = { - check(a: number, b: number, c: number, d: boolean): void; + check(a: number, b: number, c: number, d: number, e: boolean): void; } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.js index 761397287..0a92510f7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -71,7 +72,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -85,21 +86,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -203,8 +214,8 @@ export async function createInstantiator(options, swift) { createExports: (instance) => { const js = swift.memory.heap; const exports = { - check: function bjs_check(a, b, c, d) { - instance.exports.bjs_check(a, b, c, d); + check: function bjs_check(a, b, c, d, e) { + instance.exports.bjs_check(a, b, c, d, e); }, }; _exports = exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js index a0f2c8b08..fe6c3ae04 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.d.ts index da7f59772..c726e1f5a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.d.ts @@ -6,6 +6,7 @@ export type Exports = { checkInt(): number; + checkUInt(): number; checkFloat(): number; checkDouble(): number; checkBool(): boolean; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js index ec4dd9cab..836a82f21 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -71,7 +72,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -85,21 +86,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -207,6 +218,10 @@ export async function createInstantiator(options, swift) { const ret = instance.exports.bjs_checkInt(); return ret; }, + checkUInt: function bjs_checkUInt() { + const ret = instance.exports.bjs_checkUInt(); + return ret >>> 0; + }, checkFloat: function bjs_checkFloat() { const ret = instance.exports.bjs_checkFloat(); return ret; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js index 871e16a30..e3263af05 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.Export.js index 240ee9cd5..fc13a471a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.Export.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -71,7 +72,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -85,21 +86,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.Export.d.ts index b7fddd42e..4c09ad85f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.Export.d.ts @@ -90,6 +90,10 @@ export interface MyViewController extends SwiftHeapObject { delegate: MyViewControllerDelegate; secondDelegate: MyViewControllerDelegate | null; } +export interface DelegateManager extends SwiftHeapObject { + notifyAll(): void; + delegates: MyViewControllerDelegate[]; +} export type Exports = { Helper: { new(value: number): Helper; @@ -97,6 +101,10 @@ export type Exports = { MyViewController: { new(delegate: MyViewControllerDelegate): MyViewController; } + DelegateManager: { + new(delegates: MyViewControllerDelegate[]): DelegateManager; + } + processDelegates(delegates: MyViewControllerDelegate[]): MyViewControllerDelegate[]; Direction: DirectionObject ExampleEnum: ExampleEnumObject Result: ResultObject diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.Export.js index d6b9a4f01..24c02750f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.Export.js @@ -46,7 +46,7 @@ const __bjs_createResultValuesHelpers = () => { default: throw new Error("Unknown ResultValues tag: " + String(enumTag)); } }, - raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { + lift: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { const tag = tmpRetTag | 0; switch (tag) { case ResultValues.Tag.Success: { @@ -92,6 +92,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -135,7 +136,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -149,21 +150,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -258,6 +269,10 @@ export async function createInstantiator(options, swift) { if (!importObject["TestModule"]) { importObject["TestModule"] = {}; } + importObject["TestModule"]["bjs_DelegateManager_wrap"] = function(pointer) { + const obj = DelegateManager.__construct(pointer); + return swift.memory.retain(obj); + }; importObject["TestModule"]["bjs_Helper_wrap"] = function(pointer) { const obj = Helper.__construct(pointer); return swift.memory.retain(obj); @@ -361,7 +376,7 @@ export async function createInstantiator(options, swift) { } TestModule["bjs_MyViewControllerDelegate_result_set"] = function bjs_MyViewControllerDelegate_result_set(self, value) { try { - const enumValue = enumHelpers.Result.raise(value, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + const enumValue = enumHelpers.Result.lift(value, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); swift.memory.getObject(self).result = enumValue; } catch (error) { setException(error); @@ -385,7 +400,7 @@ export async function createInstantiator(options, swift) { try { let enumValue; if (valueIsSome) { - enumValue = enumHelpers.Result.raise(valueWrappedValue, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + enumValue = enumHelpers.Result.lift(valueWrappedValue, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); } swift.memory.getObject(self).optionalResult = valueIsSome ? enumValue : null; } catch (error) { @@ -542,7 +557,7 @@ export async function createInstantiator(options, swift) { } TestModule["bjs_MyViewControllerDelegate_handleResult"] = function bjs_MyViewControllerDelegate_handleResult(self, result) { try { - const enumValue = enumHelpers.Result.raise(result, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + const enumValue = enumHelpers.Result.lift(result, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); swift.memory.getObject(self).handleResult(enumValue); } catch (error) { setException(error); @@ -669,9 +684,73 @@ export async function createInstantiator(options, swift) { instance.exports.bjs_MyViewController_secondDelegate_set(this.pointer, +isSome, isSome ? swift.memory.retain(value) : 0); } } + class DelegateManager extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_DelegateManager_deinit, DelegateManager.prototype); + } + + constructor(delegates) { + const arrayCleanups = []; + for (const elem of delegates) { + const objId = swift.memory.retain(elem); + tmpParamInts.push(objId); + } + tmpParamInts.push(delegates.length); + const ret = instance.exports.bjs_DelegateManager_init(); + for (const cleanup of arrayCleanups) { cleanup(); } + return DelegateManager.__construct(ret); + } + notifyAll() { + instance.exports.bjs_DelegateManager_notifyAll(this.pointer); + } + get delegates() { + instance.exports.bjs_DelegateManager_delegates_get(this.pointer); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const objId = tmpRetInts.pop(); + const obj = swift.memory.getObject(objId); + swift.memory.release(objId); + arrayResult.push(obj); + } + arrayResult.reverse(); + return arrayResult; + } + set delegates(value) { + const arrayCleanups = []; + for (const elem of value) { + const objId = swift.memory.retain(elem); + tmpParamInts.push(objId); + } + tmpParamInts.push(value.length); + instance.exports.bjs_DelegateManager_delegates_set(this.pointer); + for (const cleanup of arrayCleanups) { cleanup(); } + } + } const exports = { Helper, MyViewController, + DelegateManager, + processDelegates: function bjs_processDelegates(delegates) { + const arrayCleanups = []; + for (const elem of delegates) { + const objId = swift.memory.retain(elem); + tmpParamInts.push(objId); + } + tmpParamInts.push(delegates.length); + instance.exports.bjs_processDelegates(); + const arrayLen = tmpRetInts.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const objId1 = tmpRetInts.pop(); + const obj = swift.memory.getObject(objId1); + swift.memory.release(objId1); + arrayResult.push(obj); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, Direction: DirectionValues, ExampleEnum: ExampleEnumValues, Result: ResultValues, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ReExportFrom.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ReExportFrom.Import.js index 4a13f2d7d..94e22ffc4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ReExportFrom.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ReExportFrom.Import.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Export.js index 9d69f4183..8b5a54315 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Export.js @@ -39,7 +39,7 @@ const __bjs_createAPIResultValuesHelpers = () => { default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); } }, - raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { + lift: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { const tag = tmpRetTag | 0; switch (tag) { case APIResultValues.Tag.Success: { @@ -79,6 +79,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -122,7 +123,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -136,21 +137,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -319,7 +330,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.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + const ret = enumHelpers.APIResult.lift(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); if (valueCleanup) { valueCleanup(); } return ret; } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.Export.js index a7e6c44cc..e7bebfe6c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.Export.js @@ -39,7 +39,7 @@ const __bjs_createAPIResultValuesHelpers = () => { default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); } }, - raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { + lift: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { const tag = tmpRetTag | 0; switch (tag) { case APIResultValues.Tag.Success: { @@ -79,6 +79,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -122,7 +123,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -136,21 +137,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -325,7 +336,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.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + const ret = enumHelpers.APIResult.lift(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); if (valueCleanup) { valueCleanup(); } return ret; } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Export.js index 8019f2a44..ee127ed07 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Export.js @@ -33,6 +33,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -76,7 +77,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -90,21 +91,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.Export.js index 7c4c11f69..9806fc631 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.Export.js @@ -33,6 +33,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -76,7 +77,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -90,21 +91,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringEnum.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringEnum.Import.js index 7c30768f5..373b433b6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringEnum.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringEnum.Import.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.js index 891f4bb01..021adcba3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -71,7 +72,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -85,21 +86,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.js index 03a65cc47..718f776c7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.js index 489fbe092..479b313dd 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -71,7 +72,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -85,21 +86,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.js index 49fafc92e..bb5278068 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.js index f95ee4367..d04cd6507 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -71,7 +72,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -85,21 +86,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.Export.js index 8bdbfa4be..40378d042 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.Export.js @@ -77,7 +77,7 @@ const __bjs_createAPIResultValuesHelpers = () => { default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); } }, - raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { + lift: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { const tag = tmpRetTag | 0; switch (tag) { case APIResultValues.Tag.Success: { @@ -130,6 +130,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -173,7 +174,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -187,21 +188,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -412,7 +423,7 @@ export async function createInstantiator(options, swift) { bjs["invoke_js_callback_TestModule_10TestModule9APIResultO_SS"] = function(callbackId, param0Id) { try { const callback = swift.memory.getObject(callbackId); - let param0 = enumHelpers.APIResult.raise(param0Id, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + let param0 = enumHelpers.APIResult.lift(param0Id, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); const result = callback(param0); if (typeof result !== "string") { throw new TypeError("Callback must return a string"); @@ -674,7 +685,7 @@ export async function createInstantiator(options, swift) { const callback = swift.memory.getObject(callbackId); let param0; if (param0IsSome) { - param0 = enumHelpers.APIResult.raise(param0Value, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + param0 = enumHelpers.APIResult.lift(param0Value, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); } else { param0 = null; } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.ImportMacros.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.ImportMacros.js index db434c2ab..9ab218df1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.ImportMacros.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.ImportMacros.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.Export.d.ts index 1d1474510..7769ebcbe 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.Export.d.ts @@ -4,6 +4,12 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. +export const PrecisionValues: { + readonly Rough: 0.1; + readonly Fine: 0.001; +}; +export type PrecisionTag = typeof PrecisionValues[keyof typeof PrecisionValues]; + export interface DataPoint { x: number; y: number; @@ -26,8 +32,15 @@ export interface Session { id: number; owner: Greeter; } +export interface Measurement { + value: number; + precision: PrecisionTag; + optionalPrecision: PrecisionTag | null; +} export interface ConfigStruct { } +export type PrecisionObject = typeof PrecisionValues; + /// Represents a Swift heap object like a class instance or an actor instance. export interface SwiftHeapObject { /// Release the heap object. @@ -44,6 +57,7 @@ export type Exports = { new(name: string): Greeter; } roundtrip(session: Person): Person; + Precision: PrecisionObject DataPoint: { init(x: number, y: number, label: string, optCount: number | null, optFlag: boolean | null): DataPoint; } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.Export.js index 07a2f320f..a3d60d0bd 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.Export.js @@ -4,6 +4,11 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. +export const PrecisionValues = { + Rough: 0.1, + Fine: 0.001, +}; + export async function createInstantiator(options, swift) { let instance; let memory; @@ -28,6 +33,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -61,7 +67,7 @@ export async function createInstantiator(options, swift) { }; return { cleanup }; }, - raise: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { + lift: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { const isSome = tmpRetInts.pop(); let optional; if (isSome) { @@ -109,7 +115,7 @@ export async function createInstantiator(options, swift) { }; return { cleanup }; }, - raise: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { + lift: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { const isSome = tmpRetInts.pop(); let optional; if (isSome) { @@ -152,7 +158,7 @@ export async function createInstantiator(options, swift) { }; return { cleanup }; }, - raise: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { + lift: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { const isSome = tmpRetInts.pop(); let optional; if (isSome) { @@ -161,7 +167,7 @@ export async function createInstantiator(options, swift) { } else { optional = null; } - const struct = structHelpers.Address.raise(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + const struct = structHelpers.Address.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); const int = tmpRetInts.pop(); const string1 = tmpRetStrings.pop(); return { name: string1, age: int, address: struct, email: optional }; @@ -175,7 +181,7 @@ export async function createInstantiator(options, swift) { tmpParamPointers.push(value.owner.pointer); return { cleanup: undefined }; }, - raise: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { + lift: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { const ptr = tmpRetPointers.pop(); const value = _exports['Greeter'].__construct(ptr); const int = tmpRetInts.pop(); @@ -183,12 +189,41 @@ export async function createInstantiator(options, swift) { } }); }; + const __bjs_createMeasurementHelpers = () => { + return (tmpParamInts, tmpParamF32s, tmpParamF64s, tmpParamPointers, tmpRetPointers, textEncoder, swift, enumHelpers) => ({ + lower: (value) => { + tmpParamF64s.push(value.value); + tmpParamF32s.push(Math.fround(value.precision)); + const isSome = value.optionalPrecision != null; + if (isSome) { + tmpParamF32s.push(Math.fround(value.optionalPrecision)); + } else { + tmpParamF32s.push(0.0); + } + tmpParamInts.push(isSome ? 1 : 0); + return { cleanup: undefined }; + }, + lift: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { + const isSome = tmpRetInts.pop(); + let optional; + if (isSome) { + const value = tmpRetF32s.pop(); + optional = value; + } else { + optional = null; + } + const value1 = tmpRetF32s.pop(); + const f64 = tmpRetF64s.pop(); + return { value: f64, precision: value1, optionalPrecision: optional }; + } + }); + }; const __bjs_createConfigStructHelpers = () => { return (tmpParamInts, tmpParamF32s, tmpParamF64s, tmpParamPointers, tmpRetPointers, textEncoder, swift, enumHelpers) => ({ lower: (value) => { return { cleanup: undefined }; }, - raise: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { + lift: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { return { }; } }); @@ -231,7 +266,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -245,21 +280,97 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_struct_lower_DataPoint"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.DataPoint.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_DataPoint"] = function() { + const value = structHelpers.DataPoint.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_Address"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.Address.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_Address"] = function() { + const value = structHelpers.Address.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_Person"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.Person.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_Person"] = function() { + const value = structHelpers.Person.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_Session"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.Session.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_Session"] = function() { + const value = structHelpers.Session.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_Measurement"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.Measurement.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_Measurement"] = function() { + const value = structHelpers.Measurement.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_ConfigStruct"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.ConfigStruct.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_ConfigStruct"] = function() { + const value = structHelpers.ConfigStruct.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + return swift.memory.retain(value); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -432,6 +543,9 @@ export async function createInstantiator(options, swift) { const SessionHelpers = __bjs_createSessionHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, tmpParamPointers, tmpRetPointers, textEncoder, swift, enumHelpers); structHelpers.Session = SessionHelpers; + const MeasurementHelpers = __bjs_createMeasurementHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, tmpParamPointers, tmpRetPointers, textEncoder, swift, enumHelpers); + structHelpers.Measurement = MeasurementHelpers; + const ConfigStructHelpers = __bjs_createConfigStructHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, tmpParamPointers, tmpRetPointers, textEncoder, swift, enumHelpers); structHelpers.ConfigStruct = ConfigStructHelpers; @@ -440,10 +554,11 @@ export async function createInstantiator(options, swift) { roundtrip: function bjs_roundtrip(session) { const { cleanup: cleanup } = structHelpers.Person.lower(session); instance.exports.bjs_roundtrip(); - const structValue = structHelpers.Person.raise(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + const structValue = structHelpers.Person.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); if (cleanup) { cleanup(); } return structValue; }, + Precision: PrecisionValues, DataPoint: { init: function(x, y, label, optCount, optFlag) { const labelBytes = textEncoder.encode(label); @@ -451,7 +566,7 @@ export async function createInstantiator(options, swift) { const isSome = optCount != null; const isSome1 = optFlag != null; instance.exports.bjs_DataPoint_init(x, y, labelId, labelBytes.length, +isSome, isSome ? optCount : 0, +isSome1, isSome1 ? optFlag : 0); - const structValue = structHelpers.DataPoint.raise(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + const structValue = structHelpers.DataPoint.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); swift.memory.release(labelId); return structValue; }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.ImportMacros.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.ImportMacros.d.ts new file mode 100644 index 000000000..3677f1e44 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.ImportMacros.d.ts @@ -0,0 +1,22 @@ +// 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`. + +export interface Point { + x: number; + y: number; +} +export type Exports = { +} +export type Imports = { + translate(point: Point, dx: number, dy: number): Point; +} +export function createInstantiator(options: { + imports: Imports; +}, swift: any): Promise<{ + addImports: (importObject: WebAssembly.Imports) => void; + setInstance: (instance: WebAssembly.Instance) => void; + createExports: (instance: WebAssembly.Instance) => Exports; +}>; \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.ImportMacros.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.ImportMacros.js new file mode 100644 index 000000000..f4e7e61e9 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.ImportMacros.js @@ -0,0 +1,262 @@ +// 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`. + +export async function createInstantiator(options, swift) { + let instance; + let memory; + let setException; + const textDecoder = new TextDecoder("utf-8"); + const textEncoder = new TextEncoder("utf-8"); + let tmpRetString; + let tmpRetBytes; + let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + let tmpRetPointers = []; + let tmpParamPointers = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createPointHelpers = () => { + return (tmpParamInts, tmpParamF32s, tmpParamF64s, tmpParamPointers, tmpRetPointers, textEncoder, swift, enumHelpers) => ({ + lower: (value) => { + tmpParamInts.push((value.x | 0)); + tmpParamInts.push((value.y | 0)); + return { cleanup: undefined }; + }, + lift: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { + const int = tmpRetInts.pop(); + const int1 = tmpRetInts.pop(); + return { x: int1, y: int }; + } + }); + }; + + return { + /** + * @param {WebAssembly.Imports} importObject + */ + 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); + } + bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { + const source = swift.memory.getObject(sourceId); + const bytes = new Uint8Array(memory.buffer, bytesPtr); + bytes.set(source); + } + bjs["swift_js_make_js_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + return swift.memory.retain(textDecoder.decode(bytes)); + } + bjs["swift_js_init_memory_with_result"] = function(ptr, len) { + const target = new Uint8Array(memory.buffer, ptr, len); + target.set(tmpRetBytes); + tmpRetBytes = undefined; + } + bjs["swift_js_throw"] = function(id) { + tmpRetException = swift.memory.retainByRef(id); + } + bjs["swift_js_retain"] = function(id) { + return swift.memory.retainByRef(id); + } + bjs["swift_js_release"] = function(id) { + swift.memory.release(id); + } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_i32"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return tmpParamF64s.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + tmpRetPointers.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return tmpParamPointers.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_struct_lower_Point"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.Point.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_Point"] = function() { + const value = structHelpers.Point.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + return swift.memory.retain(value); + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } else { + tmpRetOptionalBool = value !== 0; + } + } + bjs["swift_js_return_optional_int"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalInt = null; + } else { + tmpRetOptionalInt = value | 0; + } + } + bjs["swift_js_return_optional_float"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalFloat = null; + } else { + tmpRetOptionalFloat = Math.fround(value); + } + } + bjs["swift_js_return_optional_double"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalDouble = null; + } else { + tmpRetOptionalDouble = value; + } + } + bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + if (isSome === 0) { + tmpRetString = null; + } else { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + bjs["swift_js_return_optional_object"] = function(isSome, objectId) { + if (isSome === 0) { + tmpRetString = null; + } else { + tmpRetString = swift.memory.getObject(objectId); + } + } + bjs["swift_js_return_optional_heap_object"] = function(isSome, pointer) { + if (isSome === 0) { + tmpRetOptionalHeapObject = null; + } else { + tmpRetOptionalHeapObject = pointer; + } + } + bjs["swift_js_get_optional_int_presence"] = function() { + return tmpRetOptionalInt != null ? 1 : 0; + } + bjs["swift_js_get_optional_int_value"] = function() { + const value = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return value; + } + bjs["swift_js_get_optional_string"] = function() { + const str = tmpRetString; + tmpRetString = undefined; + if (str == null) { + return -1; + } else { + const bytes = textEncoder.encode(str); + tmpRetBytes = bytes; + return bytes.length; + } + } + bjs["swift_js_get_optional_float_presence"] = function() { + return tmpRetOptionalFloat != null ? 1 : 0; + } + bjs["swift_js_get_optional_float_value"] = function() { + const value = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; + return value; + } + bjs["swift_js_get_optional_double_presence"] = function() { + return tmpRetOptionalDouble != null ? 1 : 0; + } + bjs["swift_js_get_optional_double_value"] = function() { + const value = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + return value; + } + bjs["swift_js_get_optional_heap_object_pointer"] = function() { + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + return pointer || 0; + } + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_translate"] = function bjs_translate(point, dx, dy) { + try { + const value = swift.memory.getObject(point); + swift.memory.release(point); + let ret = imports.translate(value, dx, dy); + return swift.memory.retain(ret); + } catch (error) { + setException(error); + } + } + }, + setInstance: (i) => { + instance = i; + memory = instance.exports.memory; + + setException = (error) => { + instance.exports._swift_js_exception.value = swift.memory.retain(error) + } + }, + /** @param {WebAssembly.Instance} instance */ + createExports: (instance) => { + const js = swift.memory.heap; + const PointHelpers = __bjs_createPointHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, tmpParamPointers, tmpRetPointers, textEncoder, swift, enumHelpers); + structHelpers.Point = PointHelpers; + + const exports = { + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js index 2bbae4fec..45c273115 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.js index 016ebaa53..5a492295a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -71,7 +72,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -85,21 +86,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.js index 8b46062c4..406d7f0f3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js index 6c44fd008..d83919051 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.Export.d.ts new file mode 100644 index 000000000..4f9aa4e4a --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.Export.d.ts @@ -0,0 +1,38 @@ +// 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`. + +export interface PointerFields { + raw: number; + mutRaw: number; + opaque: number; + ptr: number; + mutPtr: number; +} +export type Exports = { + takeUnsafeRawPointer(p: number): void; + takeUnsafeMutableRawPointer(p: number): void; + takeOpaquePointer(p: number): void; + takeUnsafePointer(p: number): void; + takeUnsafeMutablePointer(p: number): void; + returnUnsafeRawPointer(): number; + returnUnsafeMutableRawPointer(): number; + returnOpaquePointer(): number; + returnUnsafePointer(): number; + returnUnsafeMutablePointer(): number; + roundTripPointerFields(value: PointerFields): PointerFields; + PointerFields: { + init(raw: number, mutRaw: number, opaque: number, ptr: number, mutPtr: number): PointerFields; + } +} +export type Imports = { +} +export function createInstantiator(options: { + imports: Imports; +}, swift: any): Promise<{ + addImports: (importObject: WebAssembly.Imports) => void; + setInstance: (instance: WebAssembly.Instance) => void; + createExports: (instance: WebAssembly.Instance) => Exports; +}>; \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.Export.js new file mode 100644 index 000000000..2ac28b7e9 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.Export.js @@ -0,0 +1,305 @@ +// 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`. + +export async function createInstantiator(options, swift) { + let instance; + let memory; + let setException; + const textDecoder = new TextDecoder("utf-8"); + const textEncoder = new TextEncoder("utf-8"); + let tmpRetString; + let tmpRetBytes; + let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + let tmpRetPointers = []; + let tmpParamPointers = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createPointerFieldsHelpers = () => { + return (tmpParamInts, tmpParamF32s, tmpParamF64s, tmpParamPointers, tmpRetPointers, textEncoder, swift, enumHelpers) => ({ + lower: (value) => { + tmpParamPointers.push((value.raw | 0)); + tmpParamPointers.push((value.mutRaw | 0)); + tmpParamPointers.push((value.opaque | 0)); + tmpParamPointers.push((value.ptr | 0)); + tmpParamPointers.push((value.mutPtr | 0)); + return { cleanup: undefined }; + }, + lift: (tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers) => { + const pointer = tmpRetPointers.pop(); + const pointer1 = tmpRetPointers.pop(); + const pointer2 = tmpRetPointers.pop(); + const pointer3 = tmpRetPointers.pop(); + const pointer4 = tmpRetPointers.pop(); + return { raw: pointer4, mutRaw: pointer3, opaque: pointer2, ptr: pointer1, mutPtr: pointer }; + } + }); + }; + + return { + /** + * @param {WebAssembly.Imports} importObject + */ + addImports: (importObject, importsContext) => { + bjs = {}; + importObject["bjs"] = bjs; + bjs["swift_js_return_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { + const source = swift.memory.getObject(sourceId); + const bytes = new Uint8Array(memory.buffer, bytesPtr); + bytes.set(source); + } + bjs["swift_js_make_js_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + return swift.memory.retain(textDecoder.decode(bytes)); + } + bjs["swift_js_init_memory_with_result"] = function(ptr, len) { + const target = new Uint8Array(memory.buffer, ptr, len); + target.set(tmpRetBytes); + tmpRetBytes = undefined; + } + bjs["swift_js_throw"] = function(id) { + tmpRetException = swift.memory.retainByRef(id); + } + bjs["swift_js_retain"] = function(id) { + return swift.memory.retainByRef(id); + } + bjs["swift_js_release"] = function(id) { + swift.memory.release(id); + } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_i32"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return tmpParamF64s.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + tmpRetPointers.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return tmpParamPointers.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_struct_lower_PointerFields"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.PointerFields.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_PointerFields"] = function() { + const value = structHelpers.PointerFields.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + return swift.memory.retain(value); + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } else { + tmpRetOptionalBool = value !== 0; + } + } + bjs["swift_js_return_optional_int"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalInt = null; + } else { + tmpRetOptionalInt = value | 0; + } + } + bjs["swift_js_return_optional_float"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalFloat = null; + } else { + tmpRetOptionalFloat = Math.fround(value); + } + } + bjs["swift_js_return_optional_double"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalDouble = null; + } else { + tmpRetOptionalDouble = value; + } + } + bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + if (isSome === 0) { + tmpRetString = null; + } else { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + bjs["swift_js_return_optional_object"] = function(isSome, objectId) { + if (isSome === 0) { + tmpRetString = null; + } else { + tmpRetString = swift.memory.getObject(objectId); + } + } + bjs["swift_js_return_optional_heap_object"] = function(isSome, pointer) { + if (isSome === 0) { + tmpRetOptionalHeapObject = null; + } else { + tmpRetOptionalHeapObject = pointer; + } + } + bjs["swift_js_get_optional_int_presence"] = function() { + return tmpRetOptionalInt != null ? 1 : 0; + } + bjs["swift_js_get_optional_int_value"] = function() { + const value = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return value; + } + bjs["swift_js_get_optional_string"] = function() { + const str = tmpRetString; + tmpRetString = undefined; + if (str == null) { + return -1; + } else { + const bytes = textEncoder.encode(str); + tmpRetBytes = bytes; + return bytes.length; + } + } + bjs["swift_js_get_optional_float_presence"] = function() { + return tmpRetOptionalFloat != null ? 1 : 0; + } + bjs["swift_js_get_optional_float_value"] = function() { + const value = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; + return value; + } + bjs["swift_js_get_optional_double_presence"] = function() { + return tmpRetOptionalDouble != null ? 1 : 0; + } + bjs["swift_js_get_optional_double_value"] = function() { + const value = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + return value; + } + bjs["swift_js_get_optional_heap_object_pointer"] = function() { + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + return pointer || 0; + } + }, + setInstance: (i) => { + instance = i; + memory = instance.exports.memory; + + setException = (error) => { + instance.exports._swift_js_exception.value = swift.memory.retain(error) + } + }, + /** @param {WebAssembly.Instance} instance */ + createExports: (instance) => { + const js = swift.memory.heap; + const PointerFieldsHelpers = __bjs_createPointerFieldsHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, tmpParamPointers, tmpRetPointers, textEncoder, swift, enumHelpers); + structHelpers.PointerFields = PointerFieldsHelpers; + + const exports = { + takeUnsafeRawPointer: function bjs_takeUnsafeRawPointer(p) { + instance.exports.bjs_takeUnsafeRawPointer(p); + }, + takeUnsafeMutableRawPointer: function bjs_takeUnsafeMutableRawPointer(p) { + instance.exports.bjs_takeUnsafeMutableRawPointer(p); + }, + takeOpaquePointer: function bjs_takeOpaquePointer(p) { + instance.exports.bjs_takeOpaquePointer(p); + }, + takeUnsafePointer: function bjs_takeUnsafePointer(p) { + instance.exports.bjs_takeUnsafePointer(p); + }, + takeUnsafeMutablePointer: function bjs_takeUnsafeMutablePointer(p) { + instance.exports.bjs_takeUnsafeMutablePointer(p); + }, + returnUnsafeRawPointer: function bjs_returnUnsafeRawPointer() { + const ret = instance.exports.bjs_returnUnsafeRawPointer(); + return ret; + }, + returnUnsafeMutableRawPointer: function bjs_returnUnsafeMutableRawPointer() { + const ret = instance.exports.bjs_returnUnsafeMutableRawPointer(); + return ret; + }, + returnOpaquePointer: function bjs_returnOpaquePointer() { + const ret = instance.exports.bjs_returnOpaquePointer(); + return ret; + }, + returnUnsafePointer: function bjs_returnUnsafePointer() { + const ret = instance.exports.bjs_returnUnsafePointer(); + return ret; + }, + returnUnsafeMutablePointer: function bjs_returnUnsafeMutablePointer() { + const ret = instance.exports.bjs_returnUnsafeMutablePointer(); + return ret; + }, + roundTripPointerFields: function bjs_roundTripPointerFields(value) { + const { cleanup: cleanup } = structHelpers.PointerFields.lower(value); + instance.exports.bjs_roundTripPointerFields(); + const structValue = structHelpers.PointerFields.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + if (cleanup) { cleanup(); } + return structValue; + }, + PointerFields: { + init: function(raw, mutRaw, opaque, ptr, mutPtr) { + instance.exports.bjs_PointerFields_init(raw, mutRaw, opaque, ptr, mutPtr); + const structValue = structHelpers.PointerFields.lift(tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s, tmpRetPointers); + return structValue; + }, + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Export.js index 148418657..8a2fabca9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Export.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -71,7 +72,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -85,21 +86,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.js index c22ff8c5a..2944bcf5a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.js @@ -28,6 +28,7 @@ export async function createInstantiator(options, swift) { let tmpParamF64s = []; let tmpRetPointers = []; let tmpParamPointers = []; + let tmpStructCleanups = []; const enumHelpers = {}; const structHelpers = {}; @@ -72,7 +73,7 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_tag"] = function(tag) { tmpRetTag = tag; } - bjs["swift_js_push_int"] = function(v) { + bjs["swift_js_push_i32"] = function(v) { tmpRetInts.push(v | 0); } bjs["swift_js_push_f32"] = function(v) { @@ -86,21 +87,31 @@ export async function createInstantiator(options, swift) { const value = textDecoder.decode(bytes); tmpRetStrings.push(value); } - bjs["swift_js_pop_param_int32"] = function() { + bjs["swift_js_pop_i32"] = function() { return tmpParamInts.pop(); } - bjs["swift_js_pop_param_f32"] = function() { + bjs["swift_js_pop_f32"] = function() { return tmpParamF32s.pop(); } - bjs["swift_js_pop_param_f64"] = function() { + bjs["swift_js_pop_f64"] = function() { return tmpParamF64s.pop(); } bjs["swift_js_push_pointer"] = function(pointer) { tmpRetPointers.push(pointer); } - bjs["swift_js_pop_param_pointer"] = function() { + bjs["swift_js_pop_pointer"] = function() { return tmpParamPointers.pop(); } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/ArrayTypes.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/ArrayTypes.json new file mode 100644 index 000000000..c796433dd --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/ArrayTypes.json @@ -0,0 +1,983 @@ +{ + "classes" : [ + { + "methods" : [ + + ], + "name" : "Item", + "properties" : [ + + ], + "swiftCallName" : "Item" + } + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "north" + }, + { + "associatedValues" : [ + + ], + "name" : "south" + }, + { + "associatedValues" : [ + + ], + "name" : "east" + }, + { + "associatedValues" : [ + + ], + "name" : "west" + } + ], + "emitStyle" : "const", + "name" : "Direction", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Direction", + "tsFullPath" : "Direction" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "pending", + "rawValue" : "0" + }, + { + "associatedValues" : [ + + ], + "name" : "active", + "rawValue" : "1" + }, + { + "associatedValues" : [ + + ], + "name" : "completed", + "rawValue" : "2" + } + ], + "emitStyle" : "const", + "name" : "Status", + "rawType" : "Int", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Status", + "tsFullPath" : "Status" + } + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_processIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processIntArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "abiName" : "bjs_processStringArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processStringArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "abiName" : "bjs_processDoubleArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processDoubleArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + }, + { + "abiName" : "bjs_processBoolArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processBoolArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "bool" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "bool" : { + + } + } + } + } + }, + { + "abiName" : "bjs_processPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processPointArray", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + }, + { + "abiName" : "bjs_processDirectionArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processDirectionArray", + "parameters" : [ + { + "label" : "_", + "name" : "directions", + "type" : { + "array" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + }, + { + "abiName" : "bjs_processStatusArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processStatusArray", + "parameters" : [ + { + "label" : "_", + "name" : "statuses", + "type" : { + "array" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Status", + "_1" : "Int" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Status", + "_1" : "Int" + } + } + } + } + }, + { + "abiName" : "bjs_sumIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "sumIntArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_findFirstPoint", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "findFirstPoint", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + }, + { + "label" : "matching", + "name" : "matching", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Point" + } + } + }, + { + "abiName" : "bjs_processUnsafeRawPointerArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processUnsafeRawPointerArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeRawPointer" + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeRawPointer" + } + } + } + } + } + }, + { + "abiName" : "bjs_processUnsafeMutableRawPointerArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processUnsafeMutableRawPointerArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutableRawPointer" + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutableRawPointer" + } + } + } + } + } + }, + { + "abiName" : "bjs_processOpaquePointerArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOpaquePointerArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "unsafePointer" : { + "_0" : { + "kind" : "opaquePointer" + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "unsafePointer" : { + "_0" : { + "kind" : "opaquePointer" + } + } + } + } + } + }, + { + "abiName" : "bjs_processOptionalIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalIntArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_processOptionalStringArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalStringArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_processOptionalArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "optional" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_processOptionalPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalPointArray", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + } + } + }, + { + "abiName" : "bjs_processOptionalDirectionArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalDirectionArray", + "parameters" : [ + { + "label" : "_", + "name" : "directions", + "type" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + } + } + }, + { + "abiName" : "bjs_processOptionalStatusArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalStatusArray", + "parameters" : [ + { + "label" : "_", + "name" : "statuses", + "type" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Status", + "_1" : "Int" + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Status", + "_1" : "Int" + } + } + } + } + } + } + }, + { + "abiName" : "bjs_processNestedIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processNestedIntArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_processNestedStringArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processNestedStringArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_processNestedPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processNestedPointArray", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + } + } + } + }, + { + "abiName" : "bjs_processItemArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processItemArray", + "parameters" : [ + { + "label" : "_", + "name" : "items", + "type" : { + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Item" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Item" + } + } + } + } + }, + { + "abiName" : "bjs_processNestedItemArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processNestedItemArray", + "parameters" : [ + { + "label" : "_", + "name" : "items", + "type" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Item" + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Item" + } + } + } + } + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + { + "methods" : [ + + ], + "name" : "Point", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "x", + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "y", + "type" : { + "double" : { + + } + } + } + ], + "swiftCallName" : "Point" + } + ] +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/ArrayTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/ArrayTypes.swift new file mode 100644 index 000000000..711694c9d --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/ArrayTypes.swift @@ -0,0 +1,694 @@ +extension Direction: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Direction { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Direction { + return Direction(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .north + case 1: + self = .south + case 2: + self = .east + case 3: + self = .west + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .north: + return 0 + case .south: + return 1 + case .east: + return 2 + case .west: + return 3 + } + } +} + +extension Status: _BridgedSwiftEnumNoPayload { +} + +extension Point: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> Point { + let y = Double.bridgeJSLiftParameter(_swift_js_pop_f64()) + let x = Double.bridgeJSLiftParameter(_swift_js_pop_f64()) + return Point(x: x, y: y) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { + _swift_js_push_f64(self.x) + _swift_js_push_f64(self.y) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Point())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Point") +fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Point") +fileprivate func _bjs_struct_lift_Point() -> Int32 +#else +fileprivate func _bjs_struct_lift_Point() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_processIntArray") +@_cdecl("bjs_processIntArray") +public func _bjs_processIntArray() -> Void { + #if arch(wasm32) + let ret = processIntArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_i32(Int32(__bjs_elem_ret))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processStringArray") +@_cdecl("bjs_processStringArray") +public func _bjs_processStringArray() -> Void { + #if arch(wasm32) + let ret = processStringArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [String] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + var __bjs_ret_elem = __bjs_elem_ret + __bjs_ret_elem.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + }} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processDoubleArray") +@_cdecl("bjs_processDoubleArray") +public func _bjs_processDoubleArray() -> Void { + #if arch(wasm32) + let ret = processDoubleArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Double] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Double.bridgeJSLiftParameter(_swift_js_pop_f64())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_f64(__bjs_elem_ret)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processBoolArray") +@_cdecl("bjs_processBoolArray") +public func _bjs_processBoolArray() -> Void { + #if arch(wasm32) + let ret = processBoolArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Bool] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Bool.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_i32(__bjs_elem_ret ? 1 : 0)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processPointArray") +@_cdecl("bjs_processPointArray") +public func _bjs_processPointArray() -> Void { + #if arch(wasm32) + let ret = processPointArray(_: { + 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)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processDirectionArray") +@_cdecl("bjs_processDirectionArray") +public func _bjs_processDirectionArray() -> Void { + #if arch(wasm32) + let ret = processDirectionArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Direction] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Direction.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_i32(Int32(__bjs_elem_ret.bridgeJSLowerParameter()))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processStatusArray") +@_cdecl("bjs_processStatusArray") +public func _bjs_processStatusArray() -> Void { + #if arch(wasm32) + let ret = processStatusArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Status] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Status.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_i32(Int32(__bjs_elem_ret.bridgeJSLowerParameter()))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_sumIntArray") +@_cdecl("bjs_sumIntArray") +public func _bjs_sumIntArray() -> Int32 { + #if arch(wasm32) + let ret = sumIntArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_findFirstPoint") +@_cdecl("bjs_findFirstPoint") +public func _bjs_findFirstPoint(_ matchingBytes: Int32, _ matchingLength: Int32) -> Void { + #if arch(wasm32) + let ret = findFirstPoint(_: { + 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 + }(), matching: String.bridgeJSLiftParameter(matchingBytes, matchingLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processUnsafeRawPointerArray") +@_cdecl("bjs_processUnsafeRawPointerArray") +public func _bjs_processUnsafeRawPointerArray() -> Void { + #if arch(wasm32) + let ret = processUnsafeRawPointerArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [UnsafeRawPointer] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(UnsafeRawPointer.bridgeJSLiftParameter(_swift_js_pop_pointer())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_pointer(__bjs_elem_ret.bridgeJSLowerReturn())} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processUnsafeMutableRawPointerArray") +@_cdecl("bjs_processUnsafeMutableRawPointerArray") +public func _bjs_processUnsafeMutableRawPointerArray() -> Void { + #if arch(wasm32) + let ret = processUnsafeMutableRawPointerArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [UnsafeMutableRawPointer] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(UnsafeMutableRawPointer.bridgeJSLiftParameter(_swift_js_pop_pointer())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_pointer(__bjs_elem_ret.bridgeJSLowerReturn())} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processOpaquePointerArray") +@_cdecl("bjs_processOpaquePointerArray") +public func _bjs_processOpaquePointerArray() -> Void { + #if arch(wasm32) + let ret = processOpaquePointerArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [OpaquePointer] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(OpaquePointer.bridgeJSLiftParameter(_swift_js_pop_pointer())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_pointer(__bjs_elem_ret.bridgeJSLowerReturn())} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processOptionalIntArray") +@_cdecl("bjs_processOptionalIntArray") +public func _bjs_processOptionalIntArray() -> Void { + #if arch(wasm32) + let ret = processOptionalIntArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __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 { + _swift_js_push_i32(Int32(__bjs_unwrapped_ret_elem))} + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processOptionalStringArray") +@_cdecl("bjs_processOptionalStringArray") +public func _bjs_processOptionalStringArray() -> Void { + #if arch(wasm32) + let ret = processOptionalStringArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32(), _swift_js_pop_i32())) + } + __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 { + var __bjs_str_ret_elem = __bjs_unwrapped_ret_elem + __bjs_str_ret_elem.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + }} + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processOptionalArray") +@_cdecl("bjs_processOptionalArray") +public func _bjs_processOptionalArray(_ values: Int32) -> Void { + #if arch(wasm32) + let ret = processOptionalArray(_: { + if values == 0 { + return Optional<[Int]>.none + } else { + return { + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }() + } + }()) + let __bjs_isSome_ret = ret != nil + if let __bjs_unwrapped_ret = ret { + for __bjs_elem_ret in __bjs_unwrapped_ret { + _swift_js_push_i32(Int32(__bjs_elem_ret))} + _swift_js_push_i32(Int32(__bjs_unwrapped_ret.count))} + _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processOptionalPointArray") +@_cdecl("bjs_processOptionalPointArray") +public func _bjs_processOptionalPointArray() -> Void { + #if arch(wasm32) + let ret = processOptionalPointArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Optional.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __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)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processOptionalDirectionArray") +@_cdecl("bjs_processOptionalDirectionArray") +public func _bjs_processOptionalDirectionArray() -> Void { + #if arch(wasm32) + let ret = processOptionalDirectionArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __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 { + _swift_js_push_i32(__bjs_unwrapped_ret_elem.bridgeJSLowerParameter())} + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processOptionalStatusArray") +@_cdecl("bjs_processOptionalStatusArray") +public func _bjs_processOptionalStatusArray() -> Void { + #if arch(wasm32) + let ret = processOptionalStatusArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __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 { + _swift_js_push_i32(__bjs_unwrapped_ret_elem.bridgeJSLowerParameter())} + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processNestedIntArray") +@_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({ + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + for __bjs_elem_ret_elem in __bjs_elem_ret { + _swift_js_push_i32(Int32(__bjs_elem_ret_elem))} + _swift_js_push_i32(Int32(__bjs_elem_ret.count))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processNestedStringArray") +@_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({ + let __count = Int(_swift_js_pop_i32()) + var __result: [String] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + for __bjs_elem_ret_elem in __bjs_elem_ret { + var __bjs_ret_elem_elem = __bjs_elem_ret_elem + __bjs_ret_elem_elem.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + }} + _swift_js_push_i32(Int32(__bjs_elem_ret.count))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processNestedPointArray") +@_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({ + 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 + }()) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + for __bjs_elem_ret_elem in __bjs_elem_ret { + __bjs_elem_ret_elem.bridgeJSLowerReturn()} + _swift_js_push_i32(Int32(__bjs_elem_ret.count))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processItemArray") +@_cdecl("bjs_processItemArray") +public func _bjs_processItemArray() -> Void { + #if arch(wasm32) + let ret = processItemArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Item] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Item.bridgeJSLiftParameter(_swift_js_pop_pointer())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_pointer(__bjs_elem_ret.bridgeJSLowerReturn())} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processNestedItemArray") +@_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({ + let __count = Int(_swift_js_pop_i32()) + var __result: [Item] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Item.bridgeJSLiftParameter(_swift_js_pop_pointer())) + } + __result.reverse() + return __result + }()) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + for __bjs_elem_ret_elem in __bjs_elem_ret { + _swift_js_push_pointer(__bjs_elem_ret_elem.bridgeJSLowerReturn())} + _swift_js_push_i32(Int32(__bjs_elem_ret.count))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Item_deinit") +@_cdecl("bjs_Item_deinit") +public func _bjs_Item_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Item: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Item_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Item_wrap") +fileprivate func _bjs_Item_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Item_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/DefaultParameters.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/DefaultParameters.json index 1a013eed0..f2e6a4e2e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/DefaultParameters.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/DefaultParameters.json @@ -728,6 +728,340 @@ } } } + }, + { + "abiName" : "bjs_testIntArrayDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testIntArrayDefault", + "parameters" : [ + { + "defaultValue" : { + "array" : { + "_0" : [ + { + "int" : { + "_0" : 1 + } + }, + { + "int" : { + "_0" : 2 + } + }, + { + "int" : { + "_0" : 3 + } + } + ] + } + }, + "label" : "values", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "abiName" : "bjs_testStringArrayDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testStringArrayDefault", + "parameters" : [ + { + "defaultValue" : { + "array" : { + "_0" : [ + { + "string" : { + "_0" : "a" + } + }, + { + "string" : { + "_0" : "b" + } + }, + { + "string" : { + "_0" : "c" + } + } + ] + } + }, + "label" : "names", + "name" : "names", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "abiName" : "bjs_testDoubleArrayDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testDoubleArrayDefault", + "parameters" : [ + { + "defaultValue" : { + "array" : { + "_0" : [ + { + "double" : { + "_0" : 1.5 + } + }, + { + "double" : { + "_0" : 2.5 + } + }, + { + "double" : { + "_0" : 3.5 + } + } + ] + } + }, + "label" : "values", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + }, + { + "abiName" : "bjs_testBoolArrayDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testBoolArrayDefault", + "parameters" : [ + { + "defaultValue" : { + "array" : { + "_0" : [ + { + "bool" : { + "_0" : true + } + }, + { + "bool" : { + "_0" : false + } + }, + { + "bool" : { + "_0" : true + } + } + ] + } + }, + "label" : "flags", + "name" : "flags", + "type" : { + "array" : { + "_0" : { + "bool" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "bool" : { + + } + } + } + } + }, + { + "abiName" : "bjs_testEmptyArrayDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testEmptyArrayDefault", + "parameters" : [ + { + "defaultValue" : { + "array" : { + "_0" : [ + + ] + } + }, + "label" : "items", + "name" : "items", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "abiName" : "bjs_testMixedWithArrayDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testMixedWithArrayDefault", + "parameters" : [ + { + "defaultValue" : { + "string" : { + "_0" : "test" + } + }, + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "defaultValue" : { + "array" : { + "_0" : [ + { + "int" : { + "_0" : 10 + } + }, + { + "int" : { + "_0" : 20 + } + }, + { + "int" : { + "_0" : 30 + } + } + ] + } + }, + "label" : "values", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "defaultValue" : { + "bool" : { + "_0" : true + } + }, + "label" : "enabled", + "name" : "enabled", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } } ], "protocols" : [ diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/DefaultParameters.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/DefaultParameters.swift index d5e5bdc48..5232bdd53 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/DefaultParameters.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/DefaultParameters.swift @@ -39,9 +39,9 @@ extension Status: _BridgedSwiftCaseEnum { extension Config: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> Config { - let enabled = Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()) - let value = Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()) - let name = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) + let enabled = Bool.bridgeJSLiftParameter(_swift_js_pop_i32()) + let value = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) + let name = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) return Config(name: name, value: value, enabled: enabled) } @@ -50,21 +50,85 @@ extension Config: _BridgedSwiftStruct { __bjs_name.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(self.value)) - _swift_js_push_int(self.enabled ? 1 : 0) + _swift_js_push_i32(Int32(self.value)) + _swift_js_push_i32(self.enabled ? 1 : 0) } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Config(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Config())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Config") +fileprivate func _bjs_struct_lower_Config(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_Config(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Config") +fileprivate func _bjs_struct_lift_Config() -> Int32 +#else +fileprivate func _bjs_struct_lift_Config() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif extension MathOperations: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> MathOperations { - let baseValue = Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()) + let baseValue = Double.bridgeJSLiftParameter(_swift_js_pop_f64()) return MathOperations(baseValue: baseValue) } @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { _swift_js_push_f64(self.baseValue) } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_MathOperations(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_MathOperations())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_MathOperations") +fileprivate func _bjs_struct_lower_MathOperations(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_MathOperations(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_MathOperations") +fileprivate func _bjs_struct_lift_MathOperations() -> Int32 +#else +fileprivate func _bjs_struct_lift_MathOperations() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif @_expose(wasm, "bjs_MathOperations_init") @_cdecl("bjs_MathOperations_init") @@ -253,6 +317,139 @@ public func _bjs_testOptionalStructWithValueDefault(_ point: Int32) -> Void { #endif } +@_expose(wasm, "bjs_testIntArrayDefault") +@_cdecl("bjs_testIntArrayDefault") +public func _bjs_testIntArrayDefault() -> Void { + #if arch(wasm32) + let ret = testIntArrayDefault(values: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_i32(Int32(__bjs_elem_ret))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testStringArrayDefault") +@_cdecl("bjs_testStringArrayDefault") +public func _bjs_testStringArrayDefault() -> Void { + #if arch(wasm32) + let ret = testStringArrayDefault(names: { + let __count = Int(_swift_js_pop_i32()) + var __result: [String] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + var __bjs_ret_elem = __bjs_elem_ret + __bjs_ret_elem.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + }} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testDoubleArrayDefault") +@_cdecl("bjs_testDoubleArrayDefault") +public func _bjs_testDoubleArrayDefault() -> Void { + #if arch(wasm32) + let ret = testDoubleArrayDefault(values: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Double] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Double.bridgeJSLiftParameter(_swift_js_pop_f64())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_f64(__bjs_elem_ret)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testBoolArrayDefault") +@_cdecl("bjs_testBoolArrayDefault") +public func _bjs_testBoolArrayDefault() -> Void { + #if arch(wasm32) + let ret = testBoolArrayDefault(flags: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Bool] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Bool.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_i32(__bjs_elem_ret ? 1 : 0)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testEmptyArrayDefault") +@_cdecl("bjs_testEmptyArrayDefault") +public func _bjs_testEmptyArrayDefault() -> Void { + #if arch(wasm32) + let ret = testEmptyArrayDefault(items: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_i32(Int32(__bjs_elem_ret))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testMixedWithArrayDefault") +@_cdecl("bjs_testMixedWithArrayDefault") +public func _bjs_testMixedWithArrayDefault(_ nameBytes: Int32, _ nameLength: Int32, _ enabled: Int32) -> Void { + #if arch(wasm32) + let ret = testMixedWithArrayDefault(name: String.bridgeJSLiftParameter(nameBytes, nameLength), values: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }(), enabled: Bool.bridgeJSLiftParameter(enabled)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_DefaultGreeter_init") @_cdecl("bjs_DefaultGreeter_init") public func _bjs_DefaultGreeter_init(_ nameBytes: Int32, _ nameLength: Int32) -> UnsafeMutableRawPointer { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.swift index 13239108f..e35da2f77 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.swift @@ -2,15 +2,15 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> APIResult { switch caseId { case 0: - return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .success(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 1: - return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) case 2: - return .flag(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .flag(Bool.bridgeJSLiftParameter(_swift_js_pop_i32())) case 3: - return .rate(Float.bridgeJSLiftParameter(_swift_js_pop_param_f32())) + return .rate(Float.bridgeJSLiftParameter(_swift_js_pop_f32())) case 4: - return .precise(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64())) + return .precise(Double.bridgeJSLiftParameter(_swift_js_pop_f64())) case 5: return .info default: @@ -29,10 +29,10 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } return Int32(0) case .failure(let param0): - _swift_js_push_int(Int32(param0)) + _swift_js_push_i32(Int32(param0)) return Int32(1) case .flag(let param0): - _swift_js_push_int(param0 ? 1 : 0) + _swift_js_push_i32(param0 ? 1 : 0) return Int32(2) case .rate(let param0): _swift_js_push_f32(param0) @@ -65,10 +65,10 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } case .failure(let param0): _swift_js_push_tag(Int32(1)) - _swift_js_push_int(Int32(param0)) + _swift_js_push_i32(Int32(param0)) case .flag(let param0): _swift_js_push_tag(Int32(2)) - _swift_js_push_int(param0 ? 1 : 0) + _swift_js_push_i32(param0 ? 1 : 0) case .rate(let param0): _swift_js_push_tag(Int32(3)) _swift_js_push_f32(param0) @@ -85,15 +85,15 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> ComplexResult { switch caseId { case 0: - return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .success(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 1: - return .error(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .error(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32())) case 2: - return .status(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .status(Bool.bridgeJSLiftParameter(_swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32()), String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 3: - return .coordinates(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64())) + return .coordinates(Double.bridgeJSLiftParameter(_swift_js_pop_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_f64())) case 4: - return .comprehensive(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .comprehensive(Bool.bridgeJSLiftParameter(_swift_js_pop_i32()), Bool.bridgeJSLiftParameter(_swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32()), Double.bridgeJSLiftParameter(_swift_js_pop_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_f64()), String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 5: return .info default: @@ -116,11 +116,11 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { __bjs_param0.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(Int32(param1)) return Int32(1) case .status(let param0, let param1, let param2): - _swift_js_push_int(param0 ? 1 : 0) - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(param0 ? 1 : 0) + _swift_js_push_i32(Int32(param1)) var __bjs_param2 = param2 __bjs_param2.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) @@ -132,10 +132,10 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_f64(param2) return Int32(3) case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): - _swift_js_push_int(param0 ? 1 : 0) - _swift_js_push_int(param1 ? 1 : 0) - _swift_js_push_int(Int32(param2)) - _swift_js_push_int(Int32(param3)) + _swift_js_push_i32(param0 ? 1 : 0) + _swift_js_push_i32(param1 ? 1 : 0) + _swift_js_push_i32(Int32(param2)) + _swift_js_push_i32(Int32(param3)) _swift_js_push_f64(param4) _swift_js_push_f64(param5) var __bjs_param6 = param6 @@ -180,11 +180,11 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { __bjs_param0.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(Int32(param1)) case .status(let param0, let param1, let param2): _swift_js_push_tag(Int32(2)) - _swift_js_push_int(param0 ? 1 : 0) - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(param0 ? 1 : 0) + _swift_js_push_i32(Int32(param1)) var __bjs_param2 = param2 __bjs_param2.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) @@ -196,10 +196,10 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_f64(param2) case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): _swift_js_push_tag(Int32(4)) - _swift_js_push_int(param0 ? 1 : 0) - _swift_js_push_int(param1 ? 1 : 0) - _swift_js_push_int(Int32(param2)) - _swift_js_push_int(Int32(param3)) + _swift_js_push_i32(param0 ? 1 : 0) + _swift_js_push_i32(param1 ? 1 : 0) + _swift_js_push_i32(Int32(param2)) + _swift_js_push_i32(Int32(param3)) _swift_js_push_f64(param4) _swift_js_push_f64(param5) var __bjs_param6 = param6 @@ -224,11 +224,11 @@ extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> Utilities.Result { switch caseId { case 0: - return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .success(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 1: - return .failure(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .failure(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32())) case 2: - return .status(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .status(Bool.bridgeJSLiftParameter(_swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32()), String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) default: fatalError("Unknown Utilities.Result case ID: \(caseId)") } @@ -249,11 +249,11 @@ extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { __bjs_param0.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(Int32(param1)) return Int32(1) case .status(let param0, let param1, let param2): - _swift_js_push_int(param0 ? 1 : 0) - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(param0 ? 1 : 0) + _swift_js_push_i32(Int32(param1)) var __bjs_param2 = param2 __bjs_param2.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) @@ -286,11 +286,11 @@ extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { __bjs_param0.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(Int32(param1)) case .status(let param0, let param1, let param2): _swift_js_push_tag(Int32(2)) - _swift_js_push_int(param0 ? 1 : 0) - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(param0 ? 1 : 0) + _swift_js_push_i32(Int32(param1)) var __bjs_param2 = param2 __bjs_param2.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) @@ -303,9 +303,9 @@ extension NetworkingResult: _BridgedSwiftAssociatedValueEnum { private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> NetworkingResult { switch caseId { case 0: - return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .success(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 1: - return .failure(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .failure(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32())) default: fatalError("Unknown NetworkingResult case ID: \(caseId)") } @@ -326,7 +326,7 @@ extension NetworkingResult: _BridgedSwiftAssociatedValueEnum { __bjs_param0.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(Int32(param1)) return Int32(1) } } @@ -355,7 +355,7 @@ extension NetworkingResult: _BridgedSwiftAssociatedValueEnum { __bjs_param0.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(Int32(param1)) } } } @@ -364,11 +364,11 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> APIOptionalResult { switch caseId { case 0: - return .success(Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .success(Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32(), _swift_js_pop_i32())) case 1: - return .failure(Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .failure(Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 2: - return .status(Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .status(Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32(), _swift_js_pop_i32())) default: fatalError("Unknown APIOptionalResult case ID: \(caseId)") } @@ -386,31 +386,31 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } } - _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + _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 { - _swift_js_push_int(Int32(__bjs_unwrapped_param0)) + _swift_js_push_i32(Int32(__bjs_unwrapped_param0)) } - _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) let __bjs_isSome_param1 = param1 != nil if let __bjs_unwrapped_param1 = param1 { - _swift_js_push_int(__bjs_unwrapped_param1 ? 1 : 0) + _swift_js_push_i32(__bjs_unwrapped_param1 ? 1 : 0) } - _swift_js_push_int(__bjs_isSome_param1 ? 1 : 0) + _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 { - _swift_js_push_int(__bjs_unwrapped_param0 ? 1 : 0) + _swift_js_push_i32(__bjs_unwrapped_param0 ? 1 : 0) } - _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) let __bjs_isSome_param1 = param1 != nil if let __bjs_unwrapped_param1 = param1 { - _swift_js_push_int(Int32(__bjs_unwrapped_param1)) + _swift_js_push_i32(Int32(__bjs_unwrapped_param1)) } - _swift_js_push_int(__bjs_isSome_param1 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) let __bjs_isSome_param2 = param2 != nil if let __bjs_unwrapped_param2 = param2 { var __bjs_str_param2 = __bjs_unwrapped_param2 @@ -418,7 +418,7 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } } - _swift_js_push_int(__bjs_isSome_param2 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param2 ? 1 : 0) return Int32(2) } } @@ -444,31 +444,31 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } } - _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) case .failure(let param0, let param1): _swift_js_push_tag(Int32(1)) let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - _swift_js_push_int(Int32(__bjs_unwrapped_param0)) + _swift_js_push_i32(Int32(__bjs_unwrapped_param0)) } - _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) let __bjs_isSome_param1 = param1 != nil if let __bjs_unwrapped_param1 = param1 { - _swift_js_push_int(__bjs_unwrapped_param1 ? 1 : 0) + _swift_js_push_i32(__bjs_unwrapped_param1 ? 1 : 0) } - _swift_js_push_int(__bjs_isSome_param1 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) case .status(let param0, let param1, let param2): _swift_js_push_tag(Int32(2)) let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - _swift_js_push_int(__bjs_unwrapped_param0 ? 1 : 0) + _swift_js_push_i32(__bjs_unwrapped_param0 ? 1 : 0) } - _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) let __bjs_isSome_param1 = param1 != nil if let __bjs_unwrapped_param1 = param1 { - _swift_js_push_int(Int32(__bjs_unwrapped_param1)) + _swift_js_push_i32(Int32(__bjs_unwrapped_param1)) } - _swift_js_push_int(__bjs_isSome_param1 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) let __bjs_isSome_param2 = param2 != nil if let __bjs_unwrapped_param2 = param2 { var __bjs_str_param2 = __bjs_unwrapped_param2 @@ -476,7 +476,7 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } } - _swift_js_push_int(__bjs_isSome_param2 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param2 ? 1 : 0) } } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.json index ab2539abf..3b45bf30f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.json @@ -29,7 +29,7 @@ "label" : "b", "name" : "b", "type" : { - "float" : { + "uint" : { } } @@ -38,7 +38,7 @@ "label" : "c", "name" : "c", "type" : { - "double" : { + "float" : { } } @@ -46,6 +46,15 @@ { "label" : "d", "name" : "d", + "type" : { + "double" : { + + } + } + }, + { + "label" : "e", + "name" : "e", "type" : { "bool" : { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.swift index bb3ea0fd8..f91e1e213 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.swift @@ -1,8 +1,8 @@ @_expose(wasm, "bjs_check") @_cdecl("bjs_check") -public func _bjs_check(_ a: Int32, _ b: Float32, _ c: Float64, _ d: Int32) -> Void { +public func _bjs_check(_ a: Int32, _ b: Int32, _ c: Float32, _ d: Float64, _ e: Int32) -> Void { #if arch(wasm32) - check(a: Int.bridgeJSLiftParameter(a), b: Float.bridgeJSLiftParameter(b), c: Double.bridgeJSLiftParameter(c), d: Bool.bridgeJSLiftParameter(d)) + check(a: Int.bridgeJSLiftParameter(a), b: UInt.bridgeJSLiftParameter(b), c: Float.bridgeJSLiftParameter(c), d: Double.bridgeJSLiftParameter(d), e: Bool.bridgeJSLiftParameter(e)) #else fatalError("Only available on WebAssembly") #endif diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.json index e63b4a242..d70b0c9b5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.json @@ -24,6 +24,23 @@ } } }, + { + "abiName" : "bjs_checkUInt", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "checkUInt", + "parameters" : [ + + ], + "returnType" : { + "uint" : { + + } + } + }, { "abiName" : "bjs_checkFloat", "effects" : { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.swift index 62b5826d3..74ee7b1c3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.swift @@ -9,6 +9,17 @@ public func _bjs_checkInt() -> Int32 { #endif } +@_expose(wasm, "bjs_checkUInt") +@_cdecl("bjs_checkUInt") +public func _bjs_checkUInt() -> Int32 { + #if arch(wasm32) + let ret = checkUInt() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_checkFloat") @_cdecl("bjs_checkFloat") public func _bjs_checkFloat() -> Float32 { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Protocol.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Protocol.json index b79a59d19..eb8f2426a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Protocol.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Protocol.json @@ -247,6 +247,68 @@ } ], "swiftCallName" : "MyViewController" + }, + { + "constructor" : { + "abiName" : "bjs_DelegateManager_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "delegates", + "name" : "delegates", + "type" : { + "array" : { + "_0" : { + "swiftProtocol" : { + "_0" : "MyViewControllerDelegate" + } + } + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_DelegateManager_notifyAll", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "notifyAll", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "DelegateManager", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "delegates", + "type" : { + "array" : { + "_0" : { + "swiftProtocol" : { + "_0" : "MyViewControllerDelegate" + } + } + } + } + } + ], + "swiftCallName" : "DelegateManager" } ], "enums" : [ @@ -394,7 +456,39 @@ ], "exposeToGlobal" : false, "functions" : [ - + { + "abiName" : "bjs_processDelegates", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processDelegates", + "parameters" : [ + { + "label" : "_", + "name" : "delegates", + "type" : { + "array" : { + "_0" : { + "swiftProtocol" : { + "_0" : "MyViewControllerDelegate" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "swiftProtocol" : { + "_0" : "MyViewControllerDelegate" + } + } + } + } + } ], "protocols" : [ { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Protocol.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Protocol.swift index 735c225f1..0558e2a1f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Protocol.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Protocol.swift @@ -366,9 +366,9 @@ extension Result: _BridgedSwiftAssociatedValueEnum { private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> Result { switch caseId { case 0: - return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .success(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 1: - return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) default: fatalError("Unknown Result case ID: \(caseId)") } @@ -385,7 +385,7 @@ extension Result: _BridgedSwiftAssociatedValueEnum { } return Int32(0) case .failure(let param0): - _swift_js_push_int(Int32(param0)) + _swift_js_push_i32(Int32(param0)) return Int32(1) } } @@ -410,7 +410,7 @@ extension Result: _BridgedSwiftAssociatedValueEnum { } case .failure(let param0): _swift_js_push_tag(Int32(1)) - _swift_js_push_int(Int32(param0)) + _swift_js_push_i32(Int32(param0)) } } } @@ -418,6 +418,28 @@ extension Result: _BridgedSwiftAssociatedValueEnum { extension Priority: _BridgedSwiftEnumNoPayload { } +@_expose(wasm, "bjs_processDelegates") +@_cdecl("bjs_processDelegates") +public func _bjs_processDelegates() -> Void { + #if arch(wasm32) + let ret = processDelegates(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [AnyMyViewControllerDelegate] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(AnyMyViewControllerDelegate.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_i32((__bjs_elem_ret as! AnyMyViewControllerDelegate).bridgeJSLowerReturn())} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_Helper_init") @_cdecl("bjs_Helper_init") public func _bjs_Helper_init(_ value: Int32) -> UnsafeMutableRawPointer { @@ -625,4 +647,91 @@ fileprivate func _bjs_MyViewController_wrap(_ pointer: UnsafeMutableRawPointer) fileprivate func _bjs_MyViewController_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { fatalError("Only available on WebAssembly") } +#endif + +@_expose(wasm, "bjs_DelegateManager_init") +@_cdecl("bjs_DelegateManager_init") +public func _bjs_DelegateManager_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = DelegateManager(delegates: { + let __count = Int(_swift_js_pop_i32()) + var __result: [AnyMyViewControllerDelegate] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(AnyMyViewControllerDelegate.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DelegateManager_notifyAll") +@_cdecl("bjs_DelegateManager_notifyAll") +public func _bjs_DelegateManager_notifyAll(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + DelegateManager.bridgeJSLiftParameter(_self).notifyAll() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DelegateManager_delegates_get") +@_cdecl("bjs_DelegateManager_delegates_get") +public func _bjs_DelegateManager_delegates_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = DelegateManager.bridgeJSLiftParameter(_self).delegates + for __bjs_elem_ret in ret { + _swift_js_push_i32((__bjs_elem_ret as! AnyMyViewControllerDelegate).bridgeJSLowerReturn())} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DelegateManager_delegates_set") +@_cdecl("bjs_DelegateManager_delegates_set") +public func _bjs_DelegateManager_delegates_set(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + DelegateManager.bridgeJSLiftParameter(_self).delegates = { + let __count = Int(_swift_js_pop_i32()) + var __result: [AnyMyViewControllerDelegate] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(AnyMyViewControllerDelegate.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DelegateManager_deinit") +@_cdecl("bjs_DelegateManager_deinit") +public func _bjs_DelegateManager_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension DelegateManager: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_DelegateManager_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_DelegateManager_wrap") +fileprivate func _bjs_DelegateManager_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_DelegateManager_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} #endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticFunctions.Global.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticFunctions.Global.swift index 8a5b56065..378eff8bb 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticFunctions.Global.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticFunctions.Global.swift @@ -48,9 +48,9 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> APIResult { switch caseId { case 0: - return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .success(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 1: - return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) default: fatalError("Unknown APIResult case ID: \(caseId)") } @@ -67,7 +67,7 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } return Int32(0) case .failure(let param0): - _swift_js_push_int(Int32(param0)) + _swift_js_push_i32(Int32(param0)) return Int32(1) } } @@ -92,7 +92,7 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } case .failure(let param0): _swift_js_push_tag(Int32(1)) - _swift_js_push_int(Int32(param0)) + _swift_js_push_i32(Int32(param0)) } } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticFunctions.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticFunctions.swift index 8a5b56065..378eff8bb 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticFunctions.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticFunctions.swift @@ -48,9 +48,9 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> APIResult { switch caseId { case 0: - return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .success(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 1: - return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) default: fatalError("Unknown APIResult case ID: \(caseId)") } @@ -67,7 +67,7 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } return Int32(0) case .failure(let param0): - _swift_js_push_int(Int32(param0)) + _swift_js_push_i32(Int32(param0)) return Int32(1) } } @@ -92,7 +92,7 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } case .failure(let param0): _swift_js_push_tag(Int32(1)) - _swift_js_push_int(Int32(param0)) + _swift_js_push_i32(Int32(param0)) } } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClosure.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClosure.swift index 7d0ae15da..415aa54f6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClosure.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClosure.swift @@ -677,15 +677,15 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> APIResult { switch caseId { case 0: - return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .success(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 1: - return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) case 2: - return .flag(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .flag(Bool.bridgeJSLiftParameter(_swift_js_pop_i32())) case 3: - return .rate(Float.bridgeJSLiftParameter(_swift_js_pop_param_f32())) + return .rate(Float.bridgeJSLiftParameter(_swift_js_pop_f32())) case 4: - return .precise(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64())) + return .precise(Double.bridgeJSLiftParameter(_swift_js_pop_f64())) case 5: return .info default: @@ -704,10 +704,10 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } return Int32(0) case .failure(let param0): - _swift_js_push_int(Int32(param0)) + _swift_js_push_i32(Int32(param0)) return Int32(1) case .flag(let param0): - _swift_js_push_int(param0 ? 1 : 0) + _swift_js_push_i32(param0 ? 1 : 0) return Int32(2) case .rate(let param0): _swift_js_push_f32(param0) @@ -740,10 +740,10 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } case .failure(let param0): _swift_js_push_tag(Int32(1)) - _swift_js_push_int(Int32(param0)) + _swift_js_push_i32(Int32(param0)) case .flag(let param0): _swift_js_push_tag(Int32(2)) - _swift_js_push_int(param0 ? 1 : 0) + _swift_js_push_i32(param0 ? 1 : 0) case .rate(let param0): _swift_js_push_tag(Int32(3)) _swift_js_push_f32(param0) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftStruct.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftStruct.json index c6e430edf..ca8f7c625 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftStruct.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftStruct.json @@ -56,7 +56,35 @@ } ], "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "rough", + "rawValue" : "0.1" + }, + { + "associatedValues" : [ + + ], + "name" : "fine", + "rawValue" : "0.001" + } + ], + "emitStyle" : "const", + "name" : "Precision", + "rawType" : "Float", + "staticMethods" : [ + + ], + "staticProperties" : [ + ], + "swiftCallName" : "Precision", + "tsFullPath" : "Precision" + } ], "exposeToGlobal" : false, "functions" : [ @@ -345,6 +373,51 @@ ], "swiftCallName" : "Session" }, + { + "methods" : [ + + ], + "name" : "Measurement", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "value", + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "precision", + "type" : { + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "optionalPrecision", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" + } + } + } + } + } + ], + "swiftCallName" : "Measurement" + }, { "methods" : [ { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftStruct.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftStruct.swift index a09d312d3..af4428979 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftStruct.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftStruct.swift @@ -1,10 +1,13 @@ +extension Precision: _BridgedSwiftEnumNoPayload { +} + extension DataPoint: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> DataPoint { - let optFlag = Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let optCount = Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let label = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let y = Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()) - let x = Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()) + let optFlag = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let optCount = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let label = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let y = Double.bridgeJSLiftParameter(_swift_js_pop_f64()) + let x = Double.bridgeJSLiftParameter(_swift_js_pop_f64()) return DataPoint(x: x, y: y, label: label, optCount: optCount, optFlag: optFlag) } @@ -17,17 +20,49 @@ extension DataPoint: _BridgedSwiftStruct { } let __bjs_isSome_optCount = self.optCount != nil if let __bjs_unwrapped_optCount = self.optCount { - _swift_js_push_int(Int32(__bjs_unwrapped_optCount)) + _swift_js_push_i32(Int32(__bjs_unwrapped_optCount)) } - _swift_js_push_int(__bjs_isSome_optCount ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_optCount ? 1 : 0) let __bjs_isSome_optFlag = self.optFlag != nil if let __bjs_unwrapped_optFlag = self.optFlag { - _swift_js_push_int(__bjs_unwrapped_optFlag ? 1 : 0) + _swift_js_push_i32(__bjs_unwrapped_optFlag ? 1 : 0) } - _swift_js_push_int(__bjs_isSome_optFlag ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_optFlag ? 1 : 0) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_DataPoint(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_DataPoint())) } } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_DataPoint") +fileprivate func _bjs_struct_lower_DataPoint(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_DataPoint(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_DataPoint") +fileprivate func _bjs_struct_lift_DataPoint() -> Int32 +#else +fileprivate func _bjs_struct_lift_DataPoint() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + @_expose(wasm, "bjs_DataPoint_init") @_cdecl("bjs_DataPoint_init") public func _bjs_DataPoint_init(_ x: Float64, _ y: Float64, _ labelBytes: Int32, _ labelLength: Int32, _ optCountIsSome: Int32, _ optCountValue: Int32, _ optFlagIsSome: Int32, _ optFlagValue: Int32) -> Void { @@ -41,9 +76,9 @@ public func _bjs_DataPoint_init(_ x: Float64, _ y: Float64, _ labelBytes: Int32, extension Address: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> Address { - let zipCode = Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let city = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let street = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) + let zipCode = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let city = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let street = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) return Address(street: street, city: city, zipCode: zipCode) } @@ -58,18 +93,50 @@ extension Address: _BridgedSwiftStruct { } let __bjs_isSome_zipCode = self.zipCode != nil if let __bjs_unwrapped_zipCode = self.zipCode { - _swift_js_push_int(Int32(__bjs_unwrapped_zipCode)) + _swift_js_push_i32(Int32(__bjs_unwrapped_zipCode)) + } + _swift_js_push_i32(__bjs_isSome_zipCode ? 1 : 0) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Address(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) } - _swift_js_push_int(__bjs_isSome_zipCode ? 1 : 0) + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Address())) } } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Address") +fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Address") +fileprivate func _bjs_struct_lift_Address() -> Int32 +#else +fileprivate func _bjs_struct_lift_Address() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + extension Person: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> Person { - let email = Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32(), _swift_js_pop_param_int32()) + let email = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32(), _swift_js_pop_i32()) let address = Address.bridgeJSLiftParameter() - let age = Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()) - let name = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) + let age = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) + let name = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) return Person(name: name, age: age, address: address, email: email) } @@ -78,7 +145,7 @@ extension Person: _BridgedSwiftStruct { __bjs_name.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(self.age)) + _swift_js_push_i32(Int32(self.age)) self.address.bridgeJSLowerReturn() let __bjs_isSome_email = self.email != nil if let __bjs_unwrapped_email = self.email { @@ -87,22 +154,137 @@ extension Person: _BridgedSwiftStruct { _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } } - _swift_js_push_int(__bjs_isSome_email ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_email ? 1 : 0) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Person(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Person())) } } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Person") +fileprivate func _bjs_struct_lower_Person(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_Person(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Person") +fileprivate func _bjs_struct_lift_Person() -> Int32 +#else +fileprivate func _bjs_struct_lift_Person() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + extension Session: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> Session { - let owner = Greeter.bridgeJSLiftParameter(_swift_js_pop_param_pointer()) - let id = Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()) + let owner = Greeter.bridgeJSLiftParameter(_swift_js_pop_pointer()) + let id = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) return Session(id: id, owner: owner) } @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - _swift_js_push_int(Int32(self.id)) + _swift_js_push_i32(Int32(self.id)) _swift_js_push_pointer(self.owner.bridgeJSLowerReturn()) } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Session(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Session())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Session") +fileprivate func _bjs_struct_lower_Session(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_Session(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") } +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Session") +fileprivate func _bjs_struct_lift_Session() -> Int32 +#else +fileprivate func _bjs_struct_lift_Session() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +extension Measurement: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> Measurement { + let optionalPrecision = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_f32()) + let precision = Precision.bridgeJSLiftParameter(_swift_js_pop_f32()) + let value = Double.bridgeJSLiftParameter(_swift_js_pop_f64()) + return Measurement(value: value, precision: precision, optionalPrecision: optionalPrecision) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { + _swift_js_push_f64(self.value) + _swift_js_push_f32(self.precision.bridgeJSLowerParameter()) + let __bjs_isSome_optionalPrecision = self.optionalPrecision != nil + if let __bjs_unwrapped_optionalPrecision = self.optionalPrecision { + _swift_js_push_f32(__bjs_unwrapped_optionalPrecision.bridgeJSLowerParameter()) + } + _swift_js_push_i32(__bjs_isSome_optionalPrecision ? 1 : 0) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Measurement(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Measurement())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Measurement") +fileprivate func _bjs_struct_lower_Measurement(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_Measurement(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Measurement") +fileprivate func _bjs_struct_lift_Measurement() -> Int32 +#else +fileprivate func _bjs_struct_lift_Measurement() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif extension ConfigStruct: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> ConfigStruct { @@ -112,7 +294,39 @@ extension ConfigStruct: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_ConfigStruct(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_ConfigStruct())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_ConfigStruct") +fileprivate func _bjs_struct_lower_ConfigStruct(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_ConfigStruct(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_ConfigStruct") +fileprivate func _bjs_struct_lift_ConfigStruct() -> Int32 +#else +fileprivate func _bjs_struct_lift_ConfigStruct() -> Int32 { + fatalError("Only available on WebAssembly") } +#endif @_expose(wasm, "bjs_ConfigStruct_static_maxRetries_get") @_cdecl("bjs_ConfigStruct_static_maxRetries_get") diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/UnsafePointer.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/UnsafePointer.json new file mode 100644 index 000000000..f38cd9440 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/UnsafePointer.json @@ -0,0 +1,413 @@ +{ + "classes" : [ + + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_takeUnsafeRawPointer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeUnsafeRawPointer", + "parameters" : [ + { + "label" : "_", + "name" : "p", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeRawPointer" + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_takeUnsafeMutableRawPointer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeUnsafeMutableRawPointer", + "parameters" : [ + { + "label" : "_", + "name" : "p", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutableRawPointer" + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_takeOpaquePointer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeOpaquePointer", + "parameters" : [ + { + "label" : "_", + "name" : "p", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "opaquePointer" + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_takeUnsafePointer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeUnsafePointer", + "parameters" : [ + { + "label" : "_", + "name" : "p", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafePointer", + "pointee" : "UInt8" + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_takeUnsafeMutablePointer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeUnsafeMutablePointer", + "parameters" : [ + { + "label" : "_", + "name" : "p", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutablePointer", + "pointee" : "UInt8" + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_returnUnsafeRawPointer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "returnUnsafeRawPointer", + "parameters" : [ + + ], + "returnType" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeRawPointer" + } + } + } + }, + { + "abiName" : "bjs_returnUnsafeMutableRawPointer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "returnUnsafeMutableRawPointer", + "parameters" : [ + + ], + "returnType" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutableRawPointer" + } + } + } + }, + { + "abiName" : "bjs_returnOpaquePointer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "returnOpaquePointer", + "parameters" : [ + + ], + "returnType" : { + "unsafePointer" : { + "_0" : { + "kind" : "opaquePointer" + } + } + } + }, + { + "abiName" : "bjs_returnUnsafePointer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "returnUnsafePointer", + "parameters" : [ + + ], + "returnType" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafePointer", + "pointee" : "UInt8" + } + } + } + }, + { + "abiName" : "bjs_returnUnsafeMutablePointer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "returnUnsafeMutablePointer", + "parameters" : [ + + ], + "returnType" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutablePointer", + "pointee" : "UInt8" + } + } + } + }, + { + "abiName" : "bjs_roundTripPointerFields", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripPointerFields", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftStruct" : { + "_0" : "PointerFields" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "PointerFields" + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + { + "constructor" : { + "abiName" : "bjs_PointerFields_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "raw", + "name" : "raw", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeRawPointer" + } + } + } + }, + { + "label" : "mutRaw", + "name" : "mutRaw", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutableRawPointer" + } + } + } + }, + { + "label" : "opaque", + "name" : "opaque", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "opaquePointer" + } + } + } + }, + { + "label" : "ptr", + "name" : "ptr", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafePointer", + "pointee" : "UInt8" + } + } + } + }, + { + "label" : "mutPtr", + "name" : "mutPtr", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutablePointer", + "pointee" : "UInt8" + } + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "PointerFields", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "raw", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeRawPointer" + } + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "mutRaw", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutableRawPointer" + } + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "opaque", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "opaquePointer" + } + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "ptr", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafePointer", + "pointee" : "UInt8" + } + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "mutPtr", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutablePointer", + "pointee" : "UInt8" + } + } + } + } + ], + "swiftCallName" : "PointerFields" + } + ] +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/UnsafePointer.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/UnsafePointer.swift new file mode 100644 index 000000000..4c368908b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/UnsafePointer.swift @@ -0,0 +1,177 @@ +extension PointerFields: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> PointerFields { + let mutPtr = UnsafeMutablePointer.bridgeJSLiftParameter(_swift_js_pop_pointer()) + let ptr = UnsafePointer.bridgeJSLiftParameter(_swift_js_pop_pointer()) + let opaque = OpaquePointer.bridgeJSLiftParameter(_swift_js_pop_pointer()) + let mutRaw = UnsafeMutableRawPointer.bridgeJSLiftParameter(_swift_js_pop_pointer()) + let raw = UnsafeRawPointer.bridgeJSLiftParameter(_swift_js_pop_pointer()) + return PointerFields(raw: raw, mutRaw: mutRaw, opaque: opaque, ptr: ptr, mutPtr: mutPtr) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { + _swift_js_push_pointer(self.raw.bridgeJSLowerReturn()) + _swift_js_push_pointer(self.mutRaw.bridgeJSLowerReturn()) + _swift_js_push_pointer(self.opaque.bridgeJSLowerReturn()) + _swift_js_push_pointer(self.ptr.bridgeJSLowerReturn()) + _swift_js_push_pointer(self.mutPtr.bridgeJSLowerReturn()) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_PointerFields(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_PointerFields())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_PointerFields") +fileprivate func _bjs_struct_lower_PointerFields(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_PointerFields(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_PointerFields") +fileprivate func _bjs_struct_lift_PointerFields() -> Int32 +#else +fileprivate func _bjs_struct_lift_PointerFields() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_PointerFields_init") +@_cdecl("bjs_PointerFields_init") +public func _bjs_PointerFields_init(_ raw: UnsafeMutableRawPointer, _ mutRaw: UnsafeMutableRawPointer, _ opaque: UnsafeMutableRawPointer, _ ptr: UnsafeMutableRawPointer, _ mutPtr: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = PointerFields(raw: UnsafeRawPointer.bridgeJSLiftParameter(raw), mutRaw: UnsafeMutableRawPointer.bridgeJSLiftParameter(mutRaw), opaque: OpaquePointer.bridgeJSLiftParameter(opaque), ptr: UnsafePointer.bridgeJSLiftParameter(ptr), mutPtr: UnsafeMutablePointer.bridgeJSLiftParameter(mutPtr)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_takeUnsafeRawPointer") +@_cdecl("bjs_takeUnsafeRawPointer") +public func _bjs_takeUnsafeRawPointer(_ p: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + takeUnsafeRawPointer(_: UnsafeRawPointer.bridgeJSLiftParameter(p)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_takeUnsafeMutableRawPointer") +@_cdecl("bjs_takeUnsafeMutableRawPointer") +public func _bjs_takeUnsafeMutableRawPointer(_ p: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + takeUnsafeMutableRawPointer(_: UnsafeMutableRawPointer.bridgeJSLiftParameter(p)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_takeOpaquePointer") +@_cdecl("bjs_takeOpaquePointer") +public func _bjs_takeOpaquePointer(_ p: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + takeOpaquePointer(_: OpaquePointer.bridgeJSLiftParameter(p)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_takeUnsafePointer") +@_cdecl("bjs_takeUnsafePointer") +public func _bjs_takeUnsafePointer(_ p: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + takeUnsafePointer(_: UnsafePointer.bridgeJSLiftParameter(p)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_takeUnsafeMutablePointer") +@_cdecl("bjs_takeUnsafeMutablePointer") +public func _bjs_takeUnsafeMutablePointer(_ p: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + takeUnsafeMutablePointer(_: UnsafeMutablePointer.bridgeJSLiftParameter(p)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_returnUnsafeRawPointer") +@_cdecl("bjs_returnUnsafeRawPointer") +public func _bjs_returnUnsafeRawPointer() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = returnUnsafeRawPointer() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_returnUnsafeMutableRawPointer") +@_cdecl("bjs_returnUnsafeMutableRawPointer") +public func _bjs_returnUnsafeMutableRawPointer() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = returnUnsafeMutableRawPointer() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_returnOpaquePointer") +@_cdecl("bjs_returnOpaquePointer") +public func _bjs_returnOpaquePointer() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = returnOpaquePointer() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_returnUnsafePointer") +@_cdecl("bjs_returnUnsafePointer") +public func _bjs_returnUnsafePointer() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = returnUnsafePointer() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_returnUnsafeMutablePointer") +@_cdecl("bjs_returnUnsafeMutablePointer") +public func _bjs_returnUnsafeMutablePointer() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = returnUnsafeMutablePointer() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripPointerFields") +@_cdecl("bjs_roundTripPointerFields") +public func _bjs_roundTripPointerFields() -> Void { + #if arch(wasm32) + let ret = roundTripPointerFields(_: PointerFields.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/GlobalThisImports.ImportMacros.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/GlobalThisImports.ImportMacros.swift new file mode 100644 index 000000000..503da6189 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/GlobalThisImports.ImportMacros.swift @@ -0,0 +1,87 @@ +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_console_get") +fileprivate func bjs_console_get() -> Int32 +#else +fileprivate func bjs_console_get() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$console_get() throws(JSException) -> JSConsole { + let ret = bjs_console_get() + if let error = _swift_js_take_exception() { + throw error + } + return JSConsole.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_parseInt") +fileprivate func bjs_parseInt(_ string: Int32) -> Float64 +#else +fileprivate func bjs_parseInt(_ string: Int32) -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$parseInt(_ string: String) throws(JSException) -> Double { + let stringValue = string.bridgeJSLowerParameter() + let ret = bjs_parseInt(stringValue) + if let error = _swift_js_take_exception() { + throw error + } + return Double.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_JSConsole_log") +fileprivate func bjs_JSConsole_log(_ self: Int32, _ message: Int32) -> Void +#else +fileprivate func bjs_JSConsole_log(_ self: Int32, _ message: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$JSConsole_log(_ self: JSObject, _ message: String) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let messageValue = message.bridgeJSLowerParameter() + bjs_JSConsole_log(selfValue, messageValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_WebSocket_init") +fileprivate func bjs_WebSocket_init(_ url: Int32) -> Int32 +#else +fileprivate func bjs_WebSocket_init(_ url: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_WebSocket_close") +fileprivate func bjs_WebSocket_close(_ self: Int32) -> Void +#else +fileprivate func bjs_WebSocket_close(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$WebSocket_init(_ url: String) throws(JSException) -> JSObject { + let urlValue = url.bridgeJSLowerParameter() + let ret = bjs_WebSocket_init(urlValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + +func _$WebSocket_close(_ self: JSObject) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + bjs_WebSocket_close(selfValue) + if let error = _swift_js_take_exception() { + throw error + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/InvalidPropertyNames.Macros.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/InvalidPropertyNames.Macros.swift index 6fa9b6d8c..43d6a3eb9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/InvalidPropertyNames.Macros.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/InvalidPropertyNames.Macros.swift @@ -18,9 +18,27 @@ @JSClass struct WeirdNaming { @JSGetter var normalProperty: String @JSSetter func setNormalProperty(_ value: String) throws (JSException) + @JSGetter(jsName: "property-with-dashes") var property_with_dashes: Double + @JSSetter(jsName: "property-with-dashes") func setProperty_with_dashes(_ value: Double) throws (JSException) + @JSGetter(jsName: "123invalidStart") var _123invalidStart: Bool + @JSSetter(jsName: "123invalidStart") func set_123invalidStart(_ value: Bool) throws (JSException) + @JSGetter(jsName: "property with spaces") var property_with_spaces: String + @JSSetter(jsName: "property with spaces") func setProperty_with_spaces(_ value: String) throws (JSException) + @JSGetter(jsName: "@specialChar") var _specialChar: Double + @JSSetter(jsName: "@specialChar") func set_specialChar(_ value: Double) throws (JSException) + @JSGetter var constructor: String + @JSSetter func setConstructor(_ value: String) throws (JSException) @JSGetter var `for`: String @JSSetter func setFor(_ value: String) throws (JSException) @JSGetter var `Any`: String @JSSetter(jsName: "Any") func setAny(_ value: String) throws (JSException) @JSFunction func `as`() throws (JSException) -> Void + @JSFunction func `try`() throws (JSException) -> Void } + +@JSClass(jsName: "$Weird") struct _Weird { + @JSFunction init() throws (JSException) + @JSFunction(jsName: "method-with-dashes") func method_with_dashes() throws (JSException) -> Void +} + +@JSFunction func createWeirdClass() throws (JSException) -> _Weird diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/InvalidPropertyNames.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/InvalidPropertyNames.swift index ba9e925e0..0ef52d4d7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/InvalidPropertyNames.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/InvalidPropertyNames.swift @@ -32,6 +32,23 @@ func _$createWeirdObject() throws(JSException) -> WeirdNaming { return WeirdNaming.bridgeJSLiftReturn(ret) } +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_createWeirdClass") +fileprivate func bjs_createWeirdClass() -> Int32 +#else +fileprivate func bjs_createWeirdClass() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$createWeirdClass() throws(JSException) -> _Weird { + let ret = bjs_createWeirdClass() + if let error = _swift_js_take_exception() { + throw error + } + return _Weird.bridgeJSLiftReturn(ret) +} + #if arch(wasm32) @_extern(wasm, module: "Check", name: "bjs_ArrayBufferLike_byteLength_get") fileprivate func bjs_ArrayBufferLike_byteLength_get(_ self: Int32) -> Float64 @@ -79,6 +96,51 @@ fileprivate func bjs_WeirdNaming_normalProperty_get(_ self: Int32) -> Int32 { } #endif +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_WeirdNaming_property_with_dashes_get") +fileprivate func bjs_WeirdNaming_property_with_dashes_get(_ self: Int32) -> Float64 +#else +fileprivate func bjs_WeirdNaming_property_with_dashes_get(_ self: Int32) -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_WeirdNaming__123invalidStart_get") +fileprivate func bjs_WeirdNaming__123invalidStart_get(_ self: Int32) -> Int32 +#else +fileprivate func bjs_WeirdNaming__123invalidStart_get(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_WeirdNaming_property_with_spaces_get") +fileprivate func bjs_WeirdNaming_property_with_spaces_get(_ self: Int32) -> Int32 +#else +fileprivate func bjs_WeirdNaming_property_with_spaces_get(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_WeirdNaming__specialChar_get") +fileprivate func bjs_WeirdNaming__specialChar_get(_ self: Int32) -> Float64 +#else +fileprivate func bjs_WeirdNaming__specialChar_get(_ self: Int32) -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_WeirdNaming_constructor_get") +fileprivate func bjs_WeirdNaming_constructor_get(_ self: Int32) -> Int32 +#else +fileprivate func bjs_WeirdNaming_constructor_get(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + #if arch(wasm32) @_extern(wasm, module: "Check", name: "bjs_WeirdNaming_for_get") fileprivate func bjs_WeirdNaming_for_get(_ self: Int32) -> Int32 @@ -106,6 +168,51 @@ fileprivate func bjs_WeirdNaming_normalProperty_set(_ self: Int32, _ newValue: I } #endif +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_WeirdNaming_property_with_dashes_set") +fileprivate func bjs_WeirdNaming_property_with_dashes_set(_ self: Int32, _ newValue: Float64) -> Void +#else +fileprivate func bjs_WeirdNaming_property_with_dashes_set(_ self: Int32, _ newValue: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_WeirdNaming__123invalidStart_set") +fileprivate func bjs_WeirdNaming__123invalidStart_set(_ self: Int32, _ newValue: Int32) -> Void +#else +fileprivate func bjs_WeirdNaming__123invalidStart_set(_ self: Int32, _ newValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_WeirdNaming_property_with_spaces_set") +fileprivate func bjs_WeirdNaming_property_with_spaces_set(_ self: Int32, _ newValue: Int32) -> Void +#else +fileprivate func bjs_WeirdNaming_property_with_spaces_set(_ self: Int32, _ newValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_WeirdNaming__specialChar_set") +fileprivate func bjs_WeirdNaming__specialChar_set(_ self: Int32, _ newValue: Float64) -> Void +#else +fileprivate func bjs_WeirdNaming__specialChar_set(_ self: Int32, _ newValue: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_WeirdNaming_constructor_set") +fileprivate func bjs_WeirdNaming_constructor_set(_ self: Int32, _ newValue: Int32) -> Void +#else +fileprivate func bjs_WeirdNaming_constructor_set(_ self: Int32, _ newValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + #if arch(wasm32) @_extern(wasm, module: "Check", name: "bjs_WeirdNaming_for_set") fileprivate func bjs_WeirdNaming_for_set(_ self: Int32, _ newValue: Int32) -> Void @@ -133,6 +240,15 @@ fileprivate func bjs_WeirdNaming_as(_ self: Int32) -> Void { } #endif +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_WeirdNaming_try") +fileprivate func bjs_WeirdNaming_try(_ self: Int32) -> Void +#else +fileprivate func bjs_WeirdNaming_try(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + func _$WeirdNaming_normalProperty_get(_ self: JSObject) throws(JSException) -> String { let selfValue = self.bridgeJSLowerParameter() let ret = bjs_WeirdNaming_normalProperty_get(selfValue) @@ -142,6 +258,51 @@ func _$WeirdNaming_normalProperty_get(_ self: JSObject) throws(JSException) -> S return String.bridgeJSLiftReturn(ret) } +func _$WeirdNaming_property_with_dashes_get(_ self: JSObject) throws(JSException) -> Double { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_WeirdNaming_property_with_dashes_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return Double.bridgeJSLiftReturn(ret) +} + +func _$WeirdNaming__123invalidStart_get(_ self: JSObject) throws(JSException) -> Bool { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_WeirdNaming__123invalidStart_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return Bool.bridgeJSLiftReturn(ret) +} + +func _$WeirdNaming_property_with_spaces_get(_ self: JSObject) throws(JSException) -> String { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_WeirdNaming_property_with_spaces_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +func _$WeirdNaming__specialChar_get(_ self: JSObject) throws(JSException) -> Double { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_WeirdNaming__specialChar_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return Double.bridgeJSLiftReturn(ret) +} + +func _$WeirdNaming_constructor_get(_ self: JSObject) throws(JSException) -> String { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_WeirdNaming_constructor_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + func _$WeirdNaming_for_get(_ self: JSObject) throws(JSException) -> String { let selfValue = self.bridgeJSLowerParameter() let ret = bjs_WeirdNaming_for_get(selfValue) @@ -169,6 +330,51 @@ func _$WeirdNaming_normalProperty_set(_ self: JSObject, _ newValue: String) thro } } +func _$WeirdNaming_property_with_dashes_set(_ self: JSObject, _ newValue: Double) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_WeirdNaming_property_with_dashes_set(selfValue, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$WeirdNaming__123invalidStart_set(_ self: JSObject, _ newValue: Bool) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_WeirdNaming__123invalidStart_set(selfValue, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$WeirdNaming_property_with_spaces_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_WeirdNaming_property_with_spaces_set(selfValue, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$WeirdNaming__specialChar_set(_ self: JSObject, _ newValue: Double) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_WeirdNaming__specialChar_set(selfValue, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$WeirdNaming_constructor_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_WeirdNaming_constructor_set(selfValue, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + func _$WeirdNaming_for_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { let selfValue = self.bridgeJSLowerParameter() let newValueValue = newValue.bridgeJSLowerParameter() @@ -193,4 +399,46 @@ func _$WeirdNaming_as(_ self: JSObject) throws(JSException) -> Void { if let error = _swift_js_take_exception() { throw error } +} + +func _$WeirdNaming_try(_ self: JSObject) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + bjs_WeirdNaming_try(selfValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs__Weird_init") +fileprivate func bjs__Weird_init() -> Int32 +#else +fileprivate func bjs__Weird_init() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs__Weird_method_with_dashes") +fileprivate func bjs__Weird_method_with_dashes(_ self: Int32) -> Void +#else +fileprivate func bjs__Weird_method_with_dashes(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$_Weird_init() throws(JSException) -> JSObject { + let ret = bjs__Weird_init() + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + +func _$_Weird_method_with_dashes(_ self: JSObject) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + bjs__Weird_method_with_dashes(selfValue) + if let error = _swift_js_take_exception() { + throw error + } } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/SwiftStructImports.ImportMacros.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/SwiftStructImports.ImportMacros.swift new file mode 100644 index 000000000..54470e5de --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/SwiftStructImports.ImportMacros.swift @@ -0,0 +1,19 @@ +#if arch(wasm32) +@_extern(wasm, module: "Check", name: "bjs_translate") +fileprivate func bjs_translate(_ point: Int32, _ dx: Int32, _ dy: Int32) -> Int32 +#else +fileprivate func bjs_translate(_ point: Int32, _ dx: Int32, _ dy: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$translate(_ point: Point, _ dx: Int, _ dy: Int) throws(JSException) -> Point { + let pointObjectId = point.bridgeJSLowerParameter() + let dxValue = dx.bridgeJSLowerParameter() + let dyValue = dy.bridgeJSLowerParameter() + let ret = bjs_translate(pointObjectId, dxValue, dyValue) + if let error = _swift_js_take_exception() { + throw error + } + return Point.bridgeJSLiftReturn(ret) +} \ No newline at end of file diff --git a/Plugins/PackageToJS/Templates/bin/test.js b/Plugins/PackageToJS/Templates/bin/test.js index 1d48b6853..82ef88cc2 100644 --- a/Plugins/PackageToJS/Templates/bin/test.js +++ b/Plugins/PackageToJS/Templates/bin/test.js @@ -116,7 +116,7 @@ Hint: This typically means that a continuation leak occurred. for (const [name, fn] of Object.entries(functions)) { // Bind the page context to each function if needed // The function can optionally use the page from its closure - page.exposeFunction(name, fn); + await page.exposeFunction(name, fn); } }; } diff --git a/Plugins/PackageToJS/Templates/instantiate.js b/Plugins/PackageToJS/Templates/instantiate.js index 1ab35de35..54a7212c6 100644 --- a/Plugins/PackageToJS/Templates/instantiate.js +++ b/Plugins/PackageToJS/Templates/instantiate.js @@ -40,13 +40,13 @@ async function createInstantiator(options, swift) { swift_js_retain: unexpectedBjsCall, swift_js_release: unexpectedBjsCall, swift_js_push_tag: unexpectedBjsCall, - swift_js_push_int: unexpectedBjsCall, + swift_js_push_i32: unexpectedBjsCall, swift_js_push_f32: unexpectedBjsCall, swift_js_push_f64: unexpectedBjsCall, swift_js_push_string: unexpectedBjsCall, - swift_js_pop_param_int32: unexpectedBjsCall, - swift_js_pop_param_f32: unexpectedBjsCall, - swift_js_pop_param_f64: unexpectedBjsCall, + swift_js_pop_i32: unexpectedBjsCall, + swift_js_pop_f32: unexpectedBjsCall, + swift_js_pop_f64: unexpectedBjsCall, swift_js_return_optional_bool: unexpectedBjsCall, swift_js_return_optional_int: unexpectedBjsCall, swift_js_return_optional_string: unexpectedBjsCall, diff --git a/Plugins/PackageToJS/Templates/test.js b/Plugins/PackageToJS/Templates/test.js index 5b7090300..606040b04 100644 --- a/Plugins/PackageToJS/Templates/test.js +++ b/Plugins/PackageToJS/Templates/test.js @@ -108,10 +108,12 @@ Please run the following command to install it: page.on("console", (message) => { console.log(message.text()); }); - + + let resolveExit = undefined; const onExit = new Promise((resolve) => { - page.exposeFunction("exitTest", resolve); + resolveExit = resolve; }); + await page.exposeFunction("exitTest", resolveExit); await page.goto(`http://localhost:${address.port}/test.browser.html`); const exitCode = await onExit; await browser.close(); diff --git a/Sources/JavaScriptEventLoop/JavaScriptEventLoop+ExecutorFactory.swift b/Sources/JavaScriptEventLoop/JavaScriptEventLoop+ExecutorFactory.swift index 574e8d03a..d31e03597 100644 --- a/Sources/JavaScriptEventLoop/JavaScriptEventLoop+ExecutorFactory.swift +++ b/Sources/JavaScriptEventLoop/JavaScriptEventLoop+ExecutorFactory.swift @@ -4,7 +4,7 @@ // See: https://github.com/swiftlang/swift/pull/80266 // See: https://forums.swift.org/t/pitch-2-custom-main-and-global-executors/78437 -import _Concurrency +@_spi(ExperimentalCustomExecutors) import _Concurrency import _CJavaScriptKit #if compiler(>=6.3) @@ -12,6 +12,7 @@ import _CJavaScriptKit // MARK: - MainExecutor Implementation // MainExecutor is used by the main actor to execute tasks on the main thread @available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999, *) +@_spi(ExperimentalCustomExecutors) extension JavaScriptEventLoop: MainExecutor { public func run() throws { // This method is called from `swift_task_asyncMainDrainQueueImpl`. @@ -27,6 +28,7 @@ extension JavaScriptEventLoop: MainExecutor { extension JavaScriptEventLoop: TaskExecutor {} @available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999, *) +@_spi(ExperimentalCustomExecutors) extension JavaScriptEventLoop: SchedulingExecutor { public func enqueue( _ job: consuming ExecutorJob, @@ -65,6 +67,7 @@ extension JavaScriptEventLoop: SchedulingExecutor { // MARK: - ExecutorFactory Implementation @available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999, *) +@_spi(ExperimentalCustomExecutors) extension JavaScriptEventLoop: ExecutorFactory { // Forward all operations to the current thread's JavaScriptEventLoop instance final class CurrentThread: TaskExecutor, SchedulingExecutor, MainExecutor, SerialExecutor { diff --git a/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift b/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift index 960a59be0..4b4115602 100644 --- a/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift +++ b/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift @@ -1,5 +1,5 @@ import JavaScriptKit -import _Concurrency +@_spi(ExperimentalCustomExecutors) import _Concurrency import _CJavaScriptEventLoop import _CJavaScriptKit diff --git a/Sources/JavaScriptKit/BasicObjects/JSPromise.swift b/Sources/JavaScriptKit/BasicObjects/JSPromise.swift index c83d70673..c02ab44b0 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSPromise.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSPromise.swift @@ -31,7 +31,7 @@ public final class JSPromise: JSBridgedClass { /// is not an object and is not an instance of JavaScript `Promise`, this function will /// return `nil`. public static func construct(from value: JSValue) -> Self? { - guard case .object(let jsObject) = value else { return nil } + guard let jsObject = value.object else { return nil } return Self(jsObject) } diff --git a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift index 92ab52f04..1e7893c82 100644 --- a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift +++ b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift @@ -128,6 +128,23 @@ extension Int: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType { } } +extension UInt: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType { + // MARK: ImportTS + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + Int32(bitPattern: UInt32(self)) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> UInt { + UInt(UInt32(bitPattern: value)) + } + // MARK: ExportSwift + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> UInt { + UInt(UInt32(bitPattern: value)) + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + Int32(bitPattern: UInt32(self)) + } +} + extension Float: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType { // MARK: ImportTS @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Float32 { @@ -282,6 +299,10 @@ extension _BridgedSwiftProtocolWrapper { @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Int32 { jsObject.bridgeJSLowerReturn() } + + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Int32 { + jsObject.bridgeJSLowerParameter() + } } /// A protocol that Swift enum types that do not have a payload can conform to. @@ -322,6 +343,22 @@ public protocol _BridgedSwiftStruct: _BridgedSwiftTypeLoweredIntoVoidType { // MARK: ExportSwift @_spi(BridgeJS) static func bridgeJSLiftParameter() -> Self @_spi(BridgeJS) consuming func bridgeJSLowerReturn() -> Void + + /// Initializes a Swift struct by copying the fields from a bridged JS object. + init(unsafelyCopying jsObject: JSObject) + /// Converts the struct into a bridged JS object by copying its fields. + func toJSObject() -> JSObject +} + +extension _BridgedSwiftStruct { + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Int32 { + return toJSObject().bridgeJSLowerReturn() + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ objectId: Int32) -> Self { + let jsObject = JSObject.bridgeJSLiftReturn(objectId) + return Self(unsafelyCopying: jsObject) + } } extension _BridgedSwiftEnumNoPayload where Self: RawRepresentable, RawValue == String { @@ -388,10 +425,10 @@ where Self: RawRepresentable, RawValue: _BridgedSwiftTypeLoweredIntoSingleWasmCo #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_push_int") -@_spi(BridgeJS) public func _swift_js_push_int(_ value: Int32) +@_extern(wasm, module: "bjs", name: "swift_js_push_i32") +@_spi(BridgeJS) public func _swift_js_push_i32(_ value: Int32) #else -@_spi(BridgeJS) public func _swift_js_push_int(_ value: Int32) { +@_spi(BridgeJS) public func _swift_js_push_i32(_ value: Int32) { _onlyAvailableOnWasm() } #endif @@ -415,28 +452,39 @@ where Self: RawRepresentable, RawValue: _BridgedSwiftTypeLoweredIntoSingleWasmCo #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_pop_param_int32") -@_spi(BridgeJS) public func _swift_js_pop_param_int32() -> Int32 +@_extern(wasm, module: "bjs", name: "swift_js_pop_i32") +@_spi(BridgeJS) public func _swift_js_pop_i32() -> Int32 #else -@_spi(BridgeJS) public func _swift_js_pop_param_int32() -> Int32 { +@_spi(BridgeJS) public func _swift_js_pop_i32() -> Int32 { _onlyAvailableOnWasm() } #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_pop_param_f32") -@_spi(BridgeJS) public func _swift_js_pop_param_f32() -> Float32 +@_extern(wasm, module: "bjs", name: "swift_js_pop_f32") +@_spi(BridgeJS) public func _swift_js_pop_f32() -> Float32 #else -@_spi(BridgeJS) public func _swift_js_pop_param_f32() -> Float32 { +@_spi(BridgeJS) public func _swift_js_pop_f32() -> Float32 { _onlyAvailableOnWasm() } #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_pop_param_f64") -@_spi(BridgeJS) public func _swift_js_pop_param_f64() -> Float64 +@_extern(wasm, module: "bjs", name: "swift_js_pop_f64") +@_spi(BridgeJS) public func _swift_js_pop_f64() -> Float64 +#else +@_spi(BridgeJS) public func _swift_js_pop_f64() -> Float64 { + _onlyAvailableOnWasm() +} +#endif + +// MARK: Struct bridging helpers (JS-side lowering/raising) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_cleanup") +@_spi(BridgeJS) public func _swift_js_struct_cleanup(_ cleanupId: Int32) #else -@_spi(BridgeJS) public func _swift_js_pop_param_f64() -> Float64 { +@_spi(BridgeJS) public func _swift_js_struct_cleanup(_ cleanupId: Int32) { _onlyAvailableOnWasm() } #endif @@ -636,14 +684,142 @@ func _swift_js_return_optional_double(_ isSome: Int32, _ value: Float64) { #endif #if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_pop_param_pointer") -@_spi(BridgeJS) public func _swift_js_pop_param_pointer() -> UnsafeMutableRawPointer +@_extern(wasm, module: "bjs", name: "swift_js_pop_pointer") +@_spi(BridgeJS) public func _swift_js_pop_pointer() -> UnsafeMutableRawPointer #else -@_spi(BridgeJS) public func _swift_js_pop_param_pointer() -> UnsafeMutableRawPointer { +@_spi(BridgeJS) public func _swift_js_pop_pointer() -> UnsafeMutableRawPointer { _onlyAvailableOnWasm() } #endif +// MARK: - UnsafePointer family + +extension UnsafeMutableRawPointer { + // 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) @_transparent public consuming func bridgeJSLowerReturn() -> UnsafeMutableRawPointer { self } +} + +extension UnsafeRawPointer { + // MARK: ImportTS + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> UnsafeMutableRawPointer { + UnsafeMutableRawPointer(mutating: self) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn( + _ pointer: UnsafeMutableRawPointer + ) + -> UnsafeRawPointer + { + UnsafeRawPointer(pointer) + } + + // MARK: ExportSwift + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter( + _ pointer: UnsafeMutableRawPointer + ) + -> UnsafeRawPointer + { + UnsafeRawPointer(pointer) + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> UnsafeMutableRawPointer { + bridgeJSLowerParameter() + } +} + +extension OpaquePointer { + // MARK: ImportTS + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> UnsafeMutableRawPointer { + UnsafeMutableRawPointer(mutating: UnsafeRawPointer(self)) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn( + _ pointer: UnsafeMutableRawPointer + ) + -> OpaquePointer + { + OpaquePointer(UnsafeRawPointer(pointer)) + } + + // MARK: ExportSwift + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter( + _ pointer: UnsafeMutableRawPointer + ) + -> OpaquePointer + { + OpaquePointer(UnsafeRawPointer(pointer)) + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> UnsafeMutableRawPointer { + bridgeJSLowerParameter() + } +} + +extension UnsafePointer { + // MARK: ImportTS + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> UnsafeMutableRawPointer { + UnsafeMutableRawPointer(mutating: UnsafeRawPointer(self)) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn( + _ pointer: UnsafeMutableRawPointer + ) + -> UnsafePointer + { + UnsafeRawPointer(pointer).assumingMemoryBound(to: Pointee.self) + } + + // MARK: ExportSwift + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter( + _ pointer: UnsafeMutableRawPointer + ) + -> UnsafePointer + { + UnsafeRawPointer(pointer).assumingMemoryBound(to: Pointee.self) + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> UnsafeMutableRawPointer { + bridgeJSLowerParameter() + } +} + +extension UnsafeMutablePointer { + // MARK: ImportTS + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> 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( + _ pointer: UnsafeMutableRawPointer + ) + -> UnsafeMutablePointer + { + pointer.assumingMemoryBound(to: Pointee.self) + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> UnsafeMutableRawPointer { + bridgeJSLowerParameter() + } +} + extension Optional where Wrapped == Bool { // MARK: ImportTS @@ -739,6 +915,52 @@ extension Optional where Wrapped == Int { } } } + +extension Optional where Wrapped == UInt { + // MARK: ImportTS + + @available(*, unavailable, message: "Optional UInt type is not supported to be passed to imported JS functions") + @_spi(BridgeJS) public func bridgeJSLowerParameter() -> Void {} + + // MARK: ExportSwift + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameterWithPresence() -> ( + isSome: Int32, value: Int32 + ) { + switch consume self { + case .none: + return (isSome: 0, value: 0) + case .some(let wrapped): + return (isSome: 1, value: wrapped.bridgeJSLowerParameter()) + } + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> UInt? { + if isSome == 0 { + return nil + } else { + return UInt.bridgeJSLiftParameter(wrappedValue) + } + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> UInt? { + let isSome = _swift_js_get_optional_int_presence() + if isSome == 0 { + return nil + } else { + return UInt.bridgeJSLiftReturn(_swift_js_get_optional_int_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 Optional where Wrapped == String { // MARK: ExportSwift @@ -1269,10 +1491,10 @@ extension Optional where Wrapped: _BridgedSwiftStruct { @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { switch consume self { case .none: - _swift_js_push_int(0) // Push only isSome=0 (no struct fields) + _swift_js_push_i32(0) // Push only isSome=0 (no struct fields) case .some(let value): value.bridgeJSLowerReturn() // Push all struct fields FIRST - _swift_js_push_int(1) // Then push isSome=1 LAST (so it's popped FIRST by JS) + _swift_js_push_i32(1) // Then push isSome=1 LAST (so it's popped FIRST by JS) } } } diff --git a/Sources/JavaScriptKit/ConvertibleToJSValue.swift b/Sources/JavaScriptKit/ConvertibleToJSValue.swift index 966dbc821..3f548a46c 100644 --- a/Sources/JavaScriptKit/ConvertibleToJSValue.swift +++ b/Sources/JavaScriptKit/ConvertibleToJSValue.swift @@ -222,7 +222,7 @@ extension JSValue { let kind: JavaScriptValueKind let payload1: JavaScriptPayload1 var payload2: JavaScriptPayload2 = 0 - switch self { + switch self.storage { case .boolean(let boolValue): kind = .boolean payload1 = boolValue ? 1 : 0 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 c70533055..75f0fcca5 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 @@ -66,6 +66,7 @@ This command will: - - - +- - - - 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 new file mode 100644 index 000000000..fed56618f --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Array.md @@ -0,0 +1,132 @@ +# Exporting Swift Arrays to JS + +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/). + +BridgeJS allows you to pass Swift arrays as function parameters and return values. + +```swift +import JavaScriptKit + +@JS func processNumbers(_ values: [Int]) -> [Int] { + return values.map { $0 * 2 } +} + +@JS func getGreeting() -> [String] { + return ["Hello", "World", "from", "Swift"] +} +``` + +In JavaScript: + +```javascript +import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; +const { exports } = await init({}); + +const doubled = exports.processNumbers([1, 2, 3, 4, 5]); +console.log(doubled); // [2, 4, 6, 8, 10] + +const greeting = exports.getGreeting(); +console.log(greeting.join(" ")); // "Hello World from Swift" +``` + +The generated TypeScript declarations: + +```typescript +export type Exports = { + processNumbers(values: number[]): number[]; + getGreeting(): string[]; +} +``` + +## Arrays of Custom Types + +Arrays work with `@JS` marked structs, classes, and enums: + +```swift +@JS struct Point { + var x: Double + var y: Double +} + +@JS func scalePoints(_ points: [Point], by factor: Double) -> [Point] { + return points.map { Point(x: $0.x * factor, y: $0.y * factor) } +} +``` + +In JavaScript: + +```javascript +const points = [{ x: 1.0, y: 2.0 }, { x: 3.0, y: 4.0 }]; +const scaled = exports.scalePoints(points, 2.0); +console.log(scaled); // [{ x: 2.0, y: 4.0 }, { x: 6.0, y: 8.0 }] +``` + +## Optional and Nested Arrays + +BridgeJS supports optional arrays (`[T]?`), arrays of optionals (`[T?]`), and nested arrays (`[[T]]`): + +```swift +@JS func processOptionalInts(_ values: [Int?]) -> [Int?] { + return values.map { $0.map { $0 * 2 } } +} + +@JS func processMatrix(_ matrix: [[Int]]) -> [[Int]] { + return matrix.map { row in row.map { $0 * 2 } } +} +``` + +In JavaScript: + +```javascript +const mixed = [1, null, 3]; +console.log(exports.processOptionalInts(mixed)); // [2, null, 6] + +const matrix = [[1, 2], [3, 4]]; +console.log(exports.processMatrix(matrix)); // [[2, 4], [6, 8]] +``` + +TypeScript definitions: + +- `[Int?]` becomes `(number | null)[]` +- `[Int]?` becomes `number[] | null` +- `[[Int]]` becomes `number[][]` + +## How It Works + +Arrays use **copy semantics** when crossing the Swift/JavaScript boundary: + +1. **Data Transfer**: Array elements are pushed to type-specific stacks and reconstructed as JavaScript arrays +2. **No Shared State**: Each side has its own copy - modifications don't affect the original +3. **Element Handling**: Primitive elements are copied by value; class elements copy their references (the objects remain shared) + +This differs from classes, which use reference semantics and share state across the boundary. + +```javascript +const original = [1, 2, 3]; +const result = exports.processNumbers(original); +// original is unchanged - Swift received a copy +``` + +## Supported Features + +| Swift Feature | Status | +|:--------------|:-------| +| Primitive arrays: `[Int]`, `[Double]`, `[Bool]`, `[String]` | ✅ | +| Struct arrays: `[MyStruct]` | ✅ | +| Class arrays: `[MyClass]` | ✅ | +| Enum arrays (case, raw value, associated value) | ✅ | +| Nested arrays: `[[Int]]` | ✅ | +| Optional arrays: `[Int]?` | ✅ | +| Arrays of optionals: `[Int?]` | ✅ | +| Protocol arrays: `[MyProtocol]` | ✅ | +| UnsafePointer-family arrays: `[UnsafeRawPointer]`, `[OpaquePointer]`, etc. | ✅ | + +> Note: Array element type support matches that of regular `@JS func` parameters and return values. + +## See Also + +- 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 21925685d..f6115f063 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 @@ -110,6 +110,7 @@ The following default value types are supported for both function and constructo | Class initialization (no args) | `MyClass()` | `new MyClass()` | | Class initialization (literal args) | `MyClass("value", 42)` | `new MyClass("value", 42)` | | Struct initialization | `Point(x: 1.0, y: 2.0)` | `{ x: 1.0, y: 2.0 }` | +| Array literals | `[1, 2, 3]` | `[1, 2, 3]` | ## Working with Class and Struct Defaults @@ -156,7 +157,6 @@ The following expressions are **not supported** as default parameter values: |:----------------|:--------|:-------| | Method calls | `Date().description` | ❌ | | Closures | `{ "computed" }()` | ❌ | -| Array literals | `[1, 2, 3]` | ❌ | | Dictionary literals | `["key": "value"]` | ❌ | | Binary operations | `10 + 20` | ❌ | | Complex member access | `Config.shared.value` | ❌ | diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/Debugging.md b/Sources/JavaScriptKit/Documentation.docc/Articles/Debugging.md index f766be2ed..a8e5d77fd 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/Debugging.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/Debugging.md @@ -57,3 +57,25 @@ Alternatively, you can use the official [`C/C++ DevTools Support (DWARF)`](https ![Chrome DevTools](chrome-devtools.png) See [the DevTools team's official introduction](https://developer.chrome.com/blog/wasm-debugging-2020) for more details about the extension. + +## Bridge Call Tracing + +Enable the `Tracing` package trait to compile lightweight hook points for Swift <-> JavaScript calls. Tracing is off by default and adds no runtime overhead unless the trait is enabled: + +```bash +swift build --traits Tracing +``` + +The hooks are invoked at the start and end of each bridge crossing without collecting data for you. For example: + +```swift +let removeCallHook = JSTracing.default.addJSCallHook { info in + let started = Date() + return { print("JS call \(info) finished in \(Date().timeIntervalSince(started))s") } +} + +let removeClosureHook = JSTracing.default.addJSClosureCallHook { info in + print("JSClosure created at \(info.fileID):\(info.line)") + return nil +} +``` diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSClosure.swift b/Sources/JavaScriptKit/FundamentalObjects/JSClosure.swift index baeb29847..941b3f468 100644 --- a/Sources/JavaScriptKit/FundamentalObjects/JSClosure.swift +++ b/Sources/JavaScriptKit/FundamentalObjects/JSClosure.swift @@ -18,7 +18,11 @@ public protocol JSClosureProtocol: JSValueCompatible { public class JSOneshotClosure: JSObject, JSClosureProtocol { private var hostFuncRef: JavaScriptHostFuncRef = 0 - public init(file: String = #fileID, line: UInt32 = #line, _ body: @escaping (sending [JSValue]) -> JSValue) { + public init( + file: String = #fileID, + line: UInt32 = #line, + _ body: @escaping (sending [JSValue]) -> JSValue + ) { // 1. Fill `id` as zero at first to access `self` to get `ObjectIdentifier`. super.init(id: 0) @@ -29,12 +33,14 @@ public class JSOneshotClosure: JSObject, JSClosureProtocol { } // 3. Retain the given body in static storage by `funcRef`. - JSClosure.sharedClosures.wrappedValue[hostFuncRef] = ( - self, - { + JSClosure.sharedClosures.wrappedValue[hostFuncRef] = .init( + object: self, + body: { defer { self.release() } return body($0) - } + }, + fileID: file, + line: line ) } @@ -114,14 +120,28 @@ public class JSClosure: JSObject, JSClosureProtocol { // `removeValue(forKey:)` on a dictionary with value type containing // `sending`. Wrap the value type with a struct to avoid the crash. struct Entry { - let item: (object: JSObject, body: (sending [JSValue]) -> JSValue) + let object: JSObject + let body: (sending [JSValue]) -> JSValue + #if Tracing + let fileID: String + let line: UInt32 + #endif + + init(object: JSObject, body: @escaping (sending [JSValue]) -> JSValue, fileID: String, line: UInt32) { + self.object = object + self.body = body + #if Tracing + self.fileID = fileID + self.line = line + #endif + } } private var storage: [JavaScriptHostFuncRef: Entry] = [:] init() {} - subscript(_ key: JavaScriptHostFuncRef) -> (object: JSObject, body: (sending [JSValue]) -> JSValue)? { - get { storage[key]?.item } - set { storage[key] = newValue.map { Entry(item: $0) } } + subscript(_ key: JavaScriptHostFuncRef) -> Entry? { + get { storage[key] } + set { storage[key] = newValue } } } @@ -150,7 +170,11 @@ public class JSClosure: JSObject, JSClosureProtocol { }) } - public init(file: String = #fileID, line: UInt32 = #line, _ body: @escaping (sending [JSValue]) -> JSValue) { + public init( + file: String = #fileID, + line: UInt32 = #line, + _ body: @escaping (sending [JSValue]) -> JSValue + ) { // 1. Fill `id` as zero at first to access `self` to get `ObjectIdentifier`. super.init(id: 0) @@ -161,7 +185,12 @@ public class JSClosure: JSObject, JSClosureProtocol { } // 3. Retain the given body in static storage by `funcRef`. - Self.sharedClosures.wrappedValue[hostFuncRef] = (self, body) + Self.sharedClosures.wrappedValue[hostFuncRef] = .init( + object: self, + body: body, + fileID: file, + line: line + ) } @available(*, unavailable, message: "JSClosure does not support dictionary literal initialization") @@ -317,14 +346,22 @@ func _call_host_function_impl( _ argc: Int32, _ callbackFuncRef: JavaScriptObjectRef ) -> Bool { - guard let (_, hostFunc) = JSClosure.sharedClosures.wrappedValue[hostFuncRef] else { + guard let entry = JSClosure.sharedClosures.wrappedValue[hostFuncRef] else { return true } + #if Tracing + let traceEnd = JSTracingHooks.beginJSClosureCall( + JSTracing.JSClosureCallInfo(fileID: entry.fileID, line: UInt(entry.line)) + ) + #endif var arguments: [JSValue] = [] for i in 0.. JSObject { - arguments.withRawJSValues { rawValues in + #if Tracing + let jsValues = arguments.map { $0.jsValue } + return new(arguments: jsValues) + #else + return arguments.withRawJSValues { rawValues in rawValues.withUnsafeBufferPointer { bufferPointer in JSObject(id: swjs_call_new(self.id, bufferPointer.baseAddress!, Int32(bufferPointer.count))) } } + #endif } /// A variadic arguments version of `new`. @@ -89,8 +94,22 @@ extension JSObject { invokeNonThrowingJSFunction(arguments: arguments).jsValue } + /// Instantiate an object from this function as a constructor. + /// + /// Guaranteed to return an object because either: + /// + /// - a. the constructor explicitly returns an object, or + /// - b. the constructor returns nothing, which causes JS to return the `this` value, or + /// - c. the constructor returns undefined, null or a non-object, in which case JS also returns `this`. + /// + /// - Parameter arguments: Arguments to be passed to this constructor function. + /// - Returns: A new instance of this constructor. public func new(arguments: [JSValue]) -> JSObject { - arguments.withRawJSValues { rawValues in + #if Tracing + let traceEnd = JSTracingHooks.beginJSCall(.function(function: self, arguments: arguments)) + defer { traceEnd?() } + #endif + return arguments.withRawJSValues { rawValues in rawValues.withUnsafeBufferPointer { bufferPointer in JSObject(id: swjs_call_new(self.id, bufferPointer.baseAddress!, Int32(bufferPointer.count))) } @@ -103,22 +122,80 @@ extension JSObject { } final func invokeNonThrowingJSFunction(arguments: [JSValue]) -> RawJSValue { - arguments.withRawJSValues { invokeNonThrowingJSFunction(rawValues: $0) } - } - - final func invokeNonThrowingJSFunction(arguments: [JSValue], this: JSObject) -> RawJSValue { - arguments.withRawJSValues { invokeNonThrowingJSFunction(rawValues: $0, this: this) } + #if Tracing + let traceEnd = JSTracingHooks.beginJSCall(.function(function: self, arguments: arguments)) + #endif + let result = arguments.withRawJSValues { invokeNonThrowingJSFunction(rawValues: $0) } + #if Tracing + traceEnd?() + #endif + return result + } + + #if Tracing + final func invokeNonThrowingJSFunction( + arguments: [JSValue], + this: JSObject, + tracedMethodName: String? = nil + ) -> RawJSValue { + let traceEnd = JSTracingHooks.beginJSCall( + .method(receiver: this, methodName: tracedMethodName, arguments: arguments) + ) + let result = arguments.withRawJSValues { + invokeNonThrowingJSFunction( + rawValues: $0, + this: this + ) + } + traceEnd?() + return result + } + #else + final func invokeNonThrowingJSFunction( + arguments: [JSValue], + this: JSObject + ) -> RawJSValue { + arguments.withRawJSValues { + invokeNonThrowingJSFunction( + rawValues: $0, + this: this + ) + } } + #endif #if !hasFeature(Embedded) final func invokeNonThrowingJSFunction(arguments: [ConvertibleToJSValue]) -> RawJSValue { + #if Tracing + let jsValues = arguments.map { $0.jsValue } + return invokeNonThrowingJSFunction(arguments: jsValues) + #else arguments.withRawJSValues { invokeNonThrowingJSFunction(rawValues: $0) } + #endif } - final func invokeNonThrowingJSFunction(arguments: [ConvertibleToJSValue], this: JSObject) -> RawJSValue { + #if Tracing + final func invokeNonThrowingJSFunction( + arguments: [ConvertibleToJSValue], + this: JSObject, + tracedMethodName: String? = nil + ) -> RawJSValue { + let jsValues = arguments.map { $0.jsValue } + return invokeNonThrowingJSFunction( + arguments: jsValues, + this: this, + tracedMethodName: tracedMethodName + ) + } + #else + final func invokeNonThrowingJSFunction( + arguments: [ConvertibleToJSValue], + this: JSObject + ) -> RawJSValue { arguments.withRawJSValues { invokeNonThrowingJSFunction(rawValues: $0, this: this) } } #endif + #endif final private func invokeNonThrowingJSFunction(rawValues: [RawJSValue]) -> RawJSValue { rawValues.withUnsafeBufferPointer { [id] bufferPointer in diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift b/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift index 238b88055..caacd49f2 100644 --- a/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift +++ b/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift @@ -94,7 +94,15 @@ public class JSObject: Equatable, ExpressibleByDictionaryLiteral { public subscript(_ name: String) -> ((ConvertibleToJSValue...) -> JSValue)? { guard let function = self[name].function else { return nil } return { (arguments: ConvertibleToJSValue...) in - function(this: self, arguments: arguments) + #if Tracing + return function.invokeNonThrowingJSFunction( + arguments: arguments, + this: self, + tracedMethodName: name + ).jsValue + #else + return function.invokeNonThrowingJSFunction(arguments: arguments, this: self).jsValue + #endif } } @@ -112,7 +120,15 @@ public class JSObject: Equatable, ExpressibleByDictionaryLiteral { public subscript(_ name: JSString) -> ((ConvertibleToJSValue...) -> JSValue)? { guard let function = self[name].function else { return nil } return { (arguments: ConvertibleToJSValue...) in - function(this: self, arguments: arguments) + #if Tracing + return function.invokeNonThrowingJSFunction( + arguments: arguments, + this: self, + tracedMethodName: String(name) + ).jsValue + #else + return function.invokeNonThrowingJSFunction(arguments: arguments, this: self).jsValue + #endif } } @@ -249,7 +265,7 @@ public class JSObject: Equatable, ExpressibleByDictionaryLiteral { } public static func construct(from value: JSValue) -> Self? { - switch value { + switch value.storage { case .boolean, .string, .number, diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift b/Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift index 7c75ad556..94b5b0eca 100644 --- a/Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift +++ b/Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift @@ -77,6 +77,15 @@ private func invokeJSFunction( arguments: [ConvertibleToJSValue], this: JSObject? ) throws -> JSValue { + #if Tracing + let jsValues = arguments.map { $0.jsValue } + let traceEnd = JSTracingHooks.beginJSCall( + this.map { + .method(receiver: $0, methodName: nil, arguments: jsValues) + } ?? .function(function: jsFunc, arguments: jsValues) + ) + defer { traceEnd?() } + #endif let id = jsFunc.id let (result, isException) = arguments.withRawJSValues { rawValues in rawValues.withUnsafeBufferPointer { bufferPointer -> (JSValue, Bool) in diff --git a/Sources/JavaScriptKit/JSTracing.swift b/Sources/JavaScriptKit/JSTracing.swift new file mode 100644 index 000000000..8804e9afb --- /dev/null +++ b/Sources/JavaScriptKit/JSTracing.swift @@ -0,0 +1,133 @@ +#if Tracing + +/// Hooks for tracing Swift <-> JavaScript bridge calls. +public struct JSTracing: Sendable { + public static let `default` = JSTracing() + + public enum JSCallInfo { + case function(function: JSObject, arguments: [JSValue]) + case method(receiver: JSObject, methodName: String?, arguments: [JSValue]) + } + + /// Register a hook for Swift to JavaScript calls. + /// + /// The hook is invoked at the start of the call. Return a closure to run when + /// the call finishes, or `nil` to skip the end hook. + /// + /// - Returns: A cleanup closure that unregisters the hook. + @discardableResult + public func addJSCallHook( + _ hook: @escaping (_ info: JSCallInfo) -> (() -> Void)? + ) -> () -> Void { + JSTracingHooks.addJSCallHook(hook) + } + + public struct JSClosureCallInfo { + /// The file identifier where the called `JSClosure` was created. + public let fileID: String + /// The line number where the called `JSClosure` was created. + public let line: UInt + } + + /// Register a hook for JavaScript to Swift calls via `JSClosure`. + /// + /// The hook is invoked at the start of the call. Return a closure to run when + /// the call finishes, or `nil` to skip the end hook. + /// + /// - Returns: A cleanup closure that unregisters the hook. + @discardableResult + public func addJSClosureCallHook( + _ hook: @escaping (_ info: JSClosureCallInfo) -> (() -> Void)? + ) -> () -> Void { + JSTracingHooks.addJSClosureCallHook(hook) + } +} + +enum JSTracingHooks { + typealias HookEnd = () -> Void + typealias JSCallHook = (JSTracing.JSCallInfo) -> HookEnd? + typealias JSClosureCallHook = (JSTracing.JSClosureCallInfo) -> HookEnd? + + private final class HookList { + private var hooks: [(id: UInt, hook: Hook)] = [] + private var nextID: UInt = 0 + + var isEmpty: Bool { hooks.isEmpty } + + func add(_ hook: Hook) -> UInt { + let id = nextID + nextID &+= 1 + hooks.append((id, hook)) + return id + } + + func remove(id: UInt) { + hooks.removeAll { $0.id == id } + } + + func forEach(_ body: (Hook) -> Void) { + for entry in hooks { + body(entry.hook) + } + } + } + + private final class Storage { + let jsCallHooks = HookList() + let jsClosureCallHooks = HookList() + } + + private static let storage = LazyThreadLocal(initialize: Storage.init) + + static func addJSCallHook(_ hook: @escaping JSCallHook) -> () -> Void { + let storage = storage.wrappedValue + let id = storage.jsCallHooks.add(hook) + return { storage.jsCallHooks.remove(id: id) } + } + + static func addJSClosureCallHook(_ hook: @escaping JSClosureCallHook) -> () -> Void { + let storage = storage.wrappedValue + let id = storage.jsClosureCallHooks.add(hook) + return { storage.jsClosureCallHooks.remove(id: id) } + } + + static func beginJSCall(_ info: JSTracing.JSCallInfo) -> HookEnd? { + let storage = storage.wrappedValue + guard !storage.jsCallHooks.isEmpty else { return nil } + + var callbacks: [HookEnd] = [] + storage.jsCallHooks.forEach { hook in + if let callback = hook(info) { + callbacks.append(callback) + } + } + + guard !callbacks.isEmpty else { return nil } + return { + for callback in callbacks.reversed() { + callback() + } + } + } + + static func beginJSClosureCall(_ info: JSTracing.JSClosureCallInfo) -> HookEnd? { + let storage = storage.wrappedValue + guard !storage.jsClosureCallHooks.isEmpty else { return nil } + + var callbacks: [HookEnd] = [] + storage.jsClosureCallHooks.forEach { hook in + if let callback = hook(info) { + callbacks.append(callback) + } + } + + guard !callbacks.isEmpty else { return nil } + return { + for callback in callbacks.reversed() { + callback() + } + } + } +} + +#endif diff --git a/Sources/JavaScriptKit/JSValue.swift b/Sources/JavaScriptKit/JSValue.swift index f469a2f10..6c02e73f6 100644 --- a/Sources/JavaScriptKit/JSValue.swift +++ b/Sources/JavaScriptKit/JSValue.swift @@ -2,20 +2,55 @@ import _CJavaScriptKit /// `JSValue` represents a value in JavaScript. @dynamicMemberLookup -public enum JSValue: Equatable { - case boolean(Bool) - case string(JSString) - case number(Double) - case object(JSObject) - case null - case undefined - case symbol(JSSymbol) - case bigInt(JSBigInt) +public struct JSValue: Equatable { + /// The internal storage of the JSValue, which is intentionally not public + /// to leave the flexibility to change the storage. + internal enum Storage: Equatable { + case boolean(Bool) + case string(JSString) + case number(Double) + case object(JSObject) + case null + case undefined + case symbol(JSSymbol) + case bigInt(JSBigInt) + } + + internal var storage: Storage + + internal init(storage: Storage) { + self.storage = storage + } + + public static func boolean(_ value: Bool) -> JSValue { + .init(storage: .boolean(value)) + } + public static func string(_ value: JSString) -> JSValue { + .init(storage: .string(value)) + } + public static func number(_ value: Double) -> JSValue { + .init(storage: .number(value)) + } + public static func object(_ value: JSObject) -> JSValue { + .init(storage: .object(value)) + } + public static var null: JSValue { + .init(storage: .null) + } + public static var undefined: JSValue { + .init(storage: .undefined) + } + public static func symbol(_ value: JSSymbol) -> JSValue { + .init(storage: .symbol(value)) + } + public static func bigInt(_ value: JSBigInt) -> JSValue { + .init(storage: .bigInt(value)) + } /// Returns the `Bool` value of this JS value if its type is boolean. /// If not, returns `nil`. public var boolean: Bool? { - switch self { + switch storage { case .boolean(let boolean): return boolean default: return nil } @@ -35,7 +70,7 @@ public enum JSValue: Equatable { /// If not, returns `nil`. /// public var jsString: JSString? { - switch self { + switch storage { case .string(let string): return string default: return nil } @@ -44,7 +79,7 @@ public enum JSValue: Equatable { /// Returns the `Double` value of this JS value if the type is number. /// If not, returns `nil`. public var number: Double? { - switch self { + switch storage { case .number(let number): return number default: return nil } @@ -53,7 +88,7 @@ public enum JSValue: Equatable { /// Returns the `JSObject` of this JS value if its type is object. /// If not, returns `nil`. public var object: JSObject? { - switch self { + switch storage { case .object(let object): return object default: return nil } @@ -65,7 +100,7 @@ public enum JSValue: Equatable { /// Returns the `JSSymbol` of this JS value if its type is function. /// If not, returns `nil`. public var symbol: JSSymbol? { - switch self { + switch storage { case .symbol(let symbol): return symbol default: return nil } @@ -74,7 +109,7 @@ public enum JSValue: Equatable { /// Returns the `JSBigInt` of this JS value if its type is function. /// If not, returns `nil`. public var bigInt: JSBigInt? { - switch self { + switch storage { case .bigInt(let bigInt): return bigInt default: return nil } @@ -83,13 +118,13 @@ public enum JSValue: Equatable { /// Returns the `true` if this JS value is null. /// If not, returns `false`. public var isNull: Bool { - return self == .null + return storage == .null } /// Returns the `true` if this JS value is undefined. /// If not, returns `false`. public var isUndefined: Bool { - return self == .undefined + return storage == .undefined } } @@ -132,7 +167,7 @@ extension JSValue { extension JSValue { public static func string(_ value: String) -> JSValue { - .string(JSString(value)) + .init(storage: .string(JSString(value))) } /// Deprecated: Please create `JSClosure` directly and manage its lifetime manually. @@ -161,7 +196,7 @@ extension JSValue { /// ``` @available(*, deprecated, message: "Please create JSClosure directly and manage its lifetime manually.") public static func function(_ body: @escaping ([JSValue]) -> JSValue) -> JSValue { - .object(JSClosure(body)) + .init(storage: .object(JSClosure(body))) } @available( @@ -171,34 +206,34 @@ extension JSValue { message: "JSClosure is no longer a subclass of JSFunction. Use .object(closure) instead." ) public static func function(_ closure: JSClosure) -> JSValue { - .object(closure) + .init(storage: .object(closure)) } @available(*, deprecated, renamed: "object", message: "Use .object(function) instead") - public static func function(_ function: JSObject) -> JSValue { .object(function) } + public static func function(_ function: JSObject) -> JSValue { .init(storage: .object(function)) } } extension JSValue: ExpressibleByStringLiteral { public init(stringLiteral value: String) { - self = .string(JSString(value)) + self = .init(storage: .string(JSString(value))) } } extension JSValue: ExpressibleByIntegerLiteral { public init(integerLiteral value: Int32) { - self = .number(Double(value)) + self = .init(storage: .number(Double(value))) } } extension JSValue: ExpressibleByFloatLiteral { public init(floatLiteral value: Double) { - self = .number(value) + self = .init(storage: .number(value)) } } extension JSValue: ExpressibleByNilLiteral { public init(nilLiteral _: ()) { - self = .null + self = .init(storage: .null) } } @@ -268,7 +303,7 @@ extension JSValue { /// - Parameter constructor: The constructor function to check. /// - Returns: The result of `instanceof` in the JavaScript environment. public func isInstanceOf(_ constructor: JSObject) -> Bool { - switch self { + switch storage { case .boolean, .string, .number, .null, .undefined, .symbol, .bigInt: return false case .object(let ref): diff --git a/Sources/JavaScriptKit/JSValueDecoder.swift b/Sources/JavaScriptKit/JSValueDecoder.swift index 054c6c8da..c2ac4a681 100644 --- a/Sources/JavaScriptKit/JSValueDecoder.swift +++ b/Sources/JavaScriptKit/JSValueDecoder.swift @@ -159,7 +159,11 @@ private struct _UnkeyedDecodingContainer: UnkeyedDecodingContainer { init(decoder: _Decoder, ref: JSObject) { self.decoder = decoder - count = ref.length.number.map(Int.init) + if let count = ref.length.number { + self.count = Int(count) + } else { + self.count = nil + } self.ref = ref } diff --git a/Sources/JavaScriptKit/Macros.swift b/Sources/JavaScriptKit/Macros.swift index 8cc3dbc64..329945f2f 100644 --- a/Sources/JavaScriptKit/Macros.swift +++ b/Sources/JavaScriptKit/Macros.swift @@ -6,6 +6,13 @@ public enum JSEnumStyle: String { case tsEnum } +/// Controls where BridgeJS reads imported JS values from. +/// +/// - `global`: Read from `globalThis`. +public enum JSImportFrom: String { + case global +} + /// A macro that exposes Swift functions, classes, and methods to JavaScript. /// /// Apply this macro to Swift declarations that you want to make callable from JavaScript: @@ -112,6 +119,9 @@ public macro JS(namespace: String? = nil, enumStyle: JSEnumStyle = .const) = Bui /// /// This macro is used by BridgeJS-generated Swift declarations. /// +/// - Parameter jsName: An optional string that specifies the name of the JavaScript property to read from. +/// If not provided, the Swift property name is used. +/// /// Example: /// /// ```swift @@ -123,9 +133,12 @@ public macro JS(namespace: String? = nil, enumStyle: JSEnumStyle = .const) = Bui /// @JSGetter var name: String /// } /// ``` +/// +/// - 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() = +public macro JSGetter(jsName: String? = nil, from: JSImportFrom? = nil) = #externalMacro(module: "BridgeJSMacros", type: "JSGetterMacro") /// A macro that generates a Swift function body that writes a value to JavaScript. @@ -144,7 +157,7 @@ public macro JSGetter() = /// ``` @attached(body) @_spi(Experimental) -public macro JSSetter(jsName: String? = nil) = +public macro JSSetter(jsName: String? = nil, from: JSImportFrom? = nil) = #externalMacro(module: "BridgeJSMacros", type: "JSSetterMacro") /// A macro that generates a Swift function body that calls a JavaScript function. @@ -159,9 +172,14 @@ public macro JSSetter(jsName: String? = nil) = /// @JSFunction func greet() throws (JSException) -> String /// @JSFunction init(_ name: String) throws (JSException) /// ``` +/// +/// - Parameter jsName: An optional string that specifies the name of the JavaScript function or method to call. +/// If not provided, the Swift function name is used. +/// - 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() = +public macro JSFunction(jsName: String? = nil, from: JSImportFrom? = nil) = #externalMacro(module: "BridgeJSMacros", type: "JSFunctionMacro") /// A macro that adds bridging members for a Swift type that represents a JavaScript class. @@ -181,8 +199,11 @@ public macro JSFunction() = /// @JSFunction func greet() throws (JSException) -> String /// } /// ``` +/// +/// - Parameter from: Selects where the constructor is looked up from. +/// Use `.global` to construct globals like `WebSocket` via `globalThis`. @attached(member, names: arbitrary) @attached(extension, conformances: _JSBridgedClass) @_spi(Experimental) -public macro JSClass() = +public macro JSClass(jsName: String? = nil, from: JSImportFrom? = nil) = #externalMacro(module: "BridgeJSMacros", type: "JSClassMacro") diff --git a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift index 0df421df6..2aee862c6 100644 --- a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift +++ b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift @@ -13,6 +13,9 @@ func runJsWorks() -> Void @JS func roundTripInt(v: Int) -> Int { return v } +@JS func roundTripUInt(v: UInt) -> UInt { + return v +} @JS func roundTripFloat(v: Float) -> Float { return v } @@ -29,6 +32,22 @@ func runJsWorks() -> Void return v } +@JS func roundTripUnsafeRawPointer(v: UnsafeRawPointer) -> UnsafeRawPointer { + return v +} +@JS func roundTripUnsafeMutableRawPointer(v: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + return v +} +@JS func roundTripOpaquePointer(v: OpaquePointer) -> OpaquePointer { + return v +} +@JS func roundTripUnsafePointer(v: UnsafePointer) -> UnsafePointer { + return v +} +@JS func roundTripUnsafeMutablePointer(v: UnsafeMutablePointer) -> UnsafeMutablePointer { + return v +} + @JS func roundTripJSObject(v: JSObject) -> JSObject { return v } @@ -186,6 +205,18 @@ struct TestError: Error { case unknown = -1 } +@JS enum Precision: Float { + case rough = 0.1 + case normal = 0.01 + case fine = 0.001 +} + +@JS enum Ratio: Double { + case quarter = 0.25 + case half = 0.5 + case golden = 1.618 +} + @JS(enumStyle: .tsEnum) enum TSDirection { case north case south @@ -836,6 +867,22 @@ enum APIOptionalResult { } } +@JS func arrayWithDefault(_ values: [Int] = [1, 2, 3]) -> Int { + return values.reduce(0, +) +} + +@JS func arrayWithOptionalDefault(_ values: [Int]? = nil) -> Int { + return values?.reduce(0, +) ?? -1 +} + +@JS func arrayMixedDefaults( + prefix: String = "Sum", + values: [Int] = [10, 20], + suffix: String = "!" +) -> String { + return "\(prefix): \(values.reduce(0, +))\(suffix)" +} + // MARK: - Static Properties @JS class StaticPropertyHolder { @@ -1241,137 +1288,132 @@ enum APIOptionalResult { } } -// MARK: - Struct Tests +// MARK: - Array Tests -@JS struct DataPoint { - let x: Double - let y: Double - var label: String - var optCount: Int? - var optFlag: Bool? +// Primitive arrays +@JS func roundTripIntArray(_ values: [Int]) -> [Int] { + return values +} - @JS init(x: Double, y: Double, label: String, optCount: Int?, optFlag: Bool?) { - self.x = x - self.y = y - self.label = label - self.optCount = optCount - self.optFlag = optFlag - } +@JS func roundTripStringArray(_ values: [String]) -> [String] { + return values } -@JS struct Address { - var street: String - var city: String - var zipCode: Int? +@JS func roundTripDoubleArray(_ values: [Double]) -> [Double] { + return values } -@JS struct Contact { - var name: String - var age: Int - var address: Address - var email: String? - var secondaryAddress: Address? +@JS func roundTripBoolArray(_ values: [Bool]) -> [Bool] { + return values } -@JS struct Config { - var name: String - var theme: Theme? - var direction: Direction? - var status: Status +// Enum arrays +@JS func roundTripDirectionArray(_ values: [Direction]) -> [Direction] { + return values } -@JS struct SessionData { - var id: Int - var owner: Greeter? +@JS func roundTripStatusArray(_ values: [Status]) -> [Status] { + return values } -@JS struct ValidationReport { - var id: Int - var result: APIResult - var status: Status? - var outcome: APIResult? +@JS func roundTripThemeArray(_ values: [Theme]) -> [Theme] { + return values } -@JS struct MathOperations { - var baseValue: Double +@JS func roundTripHttpStatusArray(_ values: [HttpStatus]) -> [HttpStatus] { + return values +} - @JS init(baseValue: Double = 0.0) { - self.baseValue = baseValue - } +// Struct arrays +@JS func roundTripDataPointArray(_ points: [DataPoint]) -> [DataPoint] { + return points +} - @JS func add(a: Double, b: Double = 10.0) -> Double { - return baseValue + a + b - } +// Class arrays +@JS func roundTripGreeterArray(_ greeters: [Greeter]) -> [Greeter] { + return greeters +} - @JS func multiply(a: Double, b: Double) -> Double { - return a * b - } +// Arrays of optional elements +@JS func roundTripOptionalIntArray(_ values: [Int?]) -> [Int?] { + return values +} - @JS static func subtract(a: Double, b: Double) -> Double { - return a - b - } +@JS func roundTripOptionalStringArray(_ values: [String?]) -> [String?] { + return values } -@JS func testStructDefault( - point: DataPoint = DataPoint(x: 1.0, y: 2.0, label: "default", optCount: nil, optFlag: nil) -) -> String { - return "\(point.x),\(point.y),\(point.label)" +@JS func roundTripOptionalDataPointArray(_ points: [DataPoint?]) -> [DataPoint?] { + return points } -@JS struct ConfigStruct { - var name: String - var value: Int +@JS func roundTripOptionalDirectionArray(_ directions: [Direction?]) -> [Direction?] { + return directions +} - @JS nonisolated(unsafe) static var defaultConfig: String = "production" - @JS static let maxRetries: Int = 3 - @JS nonisolated(unsafe) static var timeout: Double = 30.0 +@JS func roundTripOptionalStatusArray(_ statuses: [Status?]) -> [Status?] { + return statuses +} - @JS static var computedSetting: String { - return "Config: \(defaultConfig)" - } +// Optional arrays +@JS func roundTripOptionalIntArrayType(_ values: [Int]?) -> [Int]? { + return values } -@JS func roundTripDataPoint(_ data: DataPoint) -> DataPoint { - return data +@JS func roundTripOptionalStringArrayType(_ values: [String]?) -> [String]? { + return values } -@JS func roundTripContact(_ contact: Contact) -> Contact { - return contact +@JS func roundTripOptionalGreeterArrayType(_ greeters: [Greeter]?) -> [Greeter]? { + return greeters } -@JS func roundTripConfig(_ config: Config) -> Config { - return config +// Nested arrays + +@JS func roundTripNestedIntArray(_ values: [[Int]]) -> [[Int]] { + return values } -@JS func roundTripSessionData(_ session: SessionData) -> SessionData { - return session +@JS func roundTripNestedStringArray(_ values: [[String]]) -> [[String]] { + return values } -@JS func roundTripValidationReport(_ report: ValidationReport) -> ValidationReport { - return report +@JS func roundTripNestedDoubleArray(_ values: [[Double]]) -> [[Double]] { + return values } -@JS func updateValidationReport(_ newResult: APIResult?, _ report: ValidationReport) -> ValidationReport { - return ValidationReport( - id: report.id, - result: newResult ?? report.result, - status: report.status, - outcome: report.outcome - ) +@JS func roundTripNestedBoolArray(_ values: [[Bool]]) -> [[Bool]] { + return values +} + +@JS func roundTripNestedDataPointArray(_ points: [[DataPoint]]) -> [[DataPoint]] { + return points } -@JS class Container { - @JS var location: DataPoint - @JS var config: Config? +@JS func roundTripNestedDirectionArray(_ directions: [[Direction]]) -> [[Direction]] { + return directions +} - @JS init(location: DataPoint, config: Config?) { - self.location = location - self.config = config - } +@JS func roundTripNestedGreeterArray(_ greeters: [[Greeter]]) -> [[Greeter]] { + return greeters +} + +@JS func roundTripUnsafeRawPointerArray(_ values: [UnsafeRawPointer]) -> [UnsafeRawPointer] { + return values +} +@JS func roundTripUnsafeMutableRawPointerArray(_ values: [UnsafeMutableRawPointer]) -> [UnsafeMutableRawPointer] { + return values +} +@JS func roundTripOpaquePointerArray(_ values: [OpaquePointer]) -> [OpaquePointer] { + return values +} + +@JS func consumeDataProcessorArrayType(_ processors: [DataProcessor]) -> Int { + return processors.count } -@JS func testContainerWithStruct(_ point: DataPoint) -> Container { - return Container(location: point, config: nil) +@JS func roundTripDataProcessorArrayType(_ processors: [DataProcessor]) -> [DataProcessor] { + return processors } class ExportAPITests: XCTestCase { diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.Macros.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.Macros.swift index 65a46a3f2..b0b24137a 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.Macros.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.Macros.swift @@ -40,3 +40,26 @@ extension FeatureFlag: _BridgedSwiftEnumNoPayload {} } @JSFunction func runAsyncWorks() throws (JSException) -> JSPromise + +@JSFunction(jsName: "$jsWeirdFunction") func _jsWeirdFunction() throws (JSException) -> Double + +@JSClass(jsName: "$WeirdClass") struct _WeirdClass { + @JSFunction init() throws (JSException) + @JSFunction(jsName: "method-with-dashes") func method_with_dashes() throws (JSException) -> String +} + +@JSFunction(from: .global) func parseInt(_ string: String) throws (JSException) -> Double + +@JSClass(from: .global) struct Animal { + @JSGetter var name: String + @JSSetter func setName(_ value: String) throws (JSException) + @JSGetter var age: Double + @JSSetter func setAge(_ value: Double) throws (JSException) + @JSGetter var isCat: Bool + @JSSetter func setIsCat(_ value: Bool) throws (JSException) + @JSFunction init(_ name: String, _ age: Double, _ isCat: Bool) throws (JSException) + @JSFunction func bark() throws (JSException) -> String + @JSFunction func getIsCat() throws (JSException) -> Bool +} + +@JSGetter(from: .global) var globalObject1: JSObject diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index 5195bee1e..35a53805d 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -1298,6 +1298,12 @@ extension Theme: _BridgedSwiftEnumNoPayload { extension HttpStatus: _BridgedSwiftEnumNoPayload { } +extension Precision: _BridgedSwiftEnumNoPayload { +} + +extension Ratio: _BridgedSwiftEnumNoPayload { +} + extension TSDirection: _BridgedSwiftCaseEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue @@ -1432,15 +1438,15 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> APIResult { switch caseId { case 0: - return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .success(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 1: - return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) case 2: - return .flag(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .flag(Bool.bridgeJSLiftParameter(_swift_js_pop_i32())) case 3: - return .rate(Float.bridgeJSLiftParameter(_swift_js_pop_param_f32())) + return .rate(Float.bridgeJSLiftParameter(_swift_js_pop_f32())) case 4: - return .precise(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64())) + return .precise(Double.bridgeJSLiftParameter(_swift_js_pop_f64())) case 5: return .info default: @@ -1459,10 +1465,10 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } return Int32(0) case .failure(let param0): - _swift_js_push_int(Int32(param0)) + _swift_js_push_i32(Int32(param0)) return Int32(1) case .flag(let param0): - _swift_js_push_int(param0 ? 1 : 0) + _swift_js_push_i32(param0 ? 1 : 0) return Int32(2) case .rate(let param0): _swift_js_push_f32(param0) @@ -1495,10 +1501,10 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } case .failure(let param0): _swift_js_push_tag(Int32(1)) - _swift_js_push_int(Int32(param0)) + _swift_js_push_i32(Int32(param0)) case .flag(let param0): _swift_js_push_tag(Int32(2)) - _swift_js_push_int(param0 ? 1 : 0) + _swift_js_push_i32(param0 ? 1 : 0) case .rate(let param0): _swift_js_push_tag(Int32(3)) _swift_js_push_f32(param0) @@ -1515,17 +1521,17 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> ComplexResult { switch caseId { case 0: - return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .success(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 1: - return .error(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .error(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32())) case 2: - return .location(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .location(Double.bridgeJSLiftParameter(_swift_js_pop_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_f64()), String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 3: - return .status(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .status(Bool.bridgeJSLiftParameter(_swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32()), String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 4: - return .coordinates(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64())) + return .coordinates(Double.bridgeJSLiftParameter(_swift_js_pop_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_f64())) case 5: - return .comprehensive(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .comprehensive(Bool.bridgeJSLiftParameter(_swift_js_pop_i32()), Bool.bridgeJSLiftParameter(_swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32()), Double.bridgeJSLiftParameter(_swift_js_pop_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_f64()), String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 6: return .info default: @@ -1548,7 +1554,7 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { __bjs_param0.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(Int32(param1)) return Int32(1) case .location(let param0, let param1, let param2): _swift_js_push_f64(param0) @@ -1559,8 +1565,8 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { } return Int32(2) case .status(let param0, let param1, let param2): - _swift_js_push_int(param0 ? 1 : 0) - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(param0 ? 1 : 0) + _swift_js_push_i32(Int32(param1)) var __bjs_param2 = param2 __bjs_param2.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) @@ -1572,10 +1578,10 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_f64(param2) return Int32(4) case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): - _swift_js_push_int(param0 ? 1 : 0) - _swift_js_push_int(param1 ? 1 : 0) - _swift_js_push_int(Int32(param2)) - _swift_js_push_int(Int32(param3)) + _swift_js_push_i32(param0 ? 1 : 0) + _swift_js_push_i32(param1 ? 1 : 0) + _swift_js_push_i32(Int32(param2)) + _swift_js_push_i32(Int32(param3)) _swift_js_push_f64(param4) _swift_js_push_f64(param5) var __bjs_param6 = param6 @@ -1620,7 +1626,7 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { __bjs_param0.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(Int32(param1)) case .location(let param0, let param1, let param2): _swift_js_push_tag(Int32(2)) _swift_js_push_f64(param0) @@ -1631,8 +1637,8 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { } case .status(let param0, let param1, let param2): _swift_js_push_tag(Int32(3)) - _swift_js_push_int(param0 ? 1 : 0) - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(param0 ? 1 : 0) + _swift_js_push_i32(Int32(param1)) var __bjs_param2 = param2 __bjs_param2.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) @@ -1644,10 +1650,10 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_f64(param2) case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): _swift_js_push_tag(Int32(5)) - _swift_js_push_int(param0 ? 1 : 0) - _swift_js_push_int(param1 ? 1 : 0) - _swift_js_push_int(Int32(param2)) - _swift_js_push_int(Int32(param3)) + _swift_js_push_i32(param0 ? 1 : 0) + _swift_js_push_i32(param1 ? 1 : 0) + _swift_js_push_i32(Int32(param2)) + _swift_js_push_i32(Int32(param3)) _swift_js_push_f64(param4) _swift_js_push_f64(param5) var __bjs_param6 = param6 @@ -1672,11 +1678,11 @@ extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> Utilities.Result { switch caseId { case 0: - return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .success(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 1: - return .failure(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .failure(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32())) case 2: - return .status(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .status(Bool.bridgeJSLiftParameter(_swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32()), String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) default: fatalError("Unknown Utilities.Result case ID: \(caseId)") } @@ -1697,11 +1703,11 @@ extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { __bjs_param0.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(Int32(param1)) return Int32(1) case .status(let param0, let param1, let param2): - _swift_js_push_int(param0 ? 1 : 0) - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(param0 ? 1 : 0) + _swift_js_push_i32(Int32(param1)) var __bjs_param2 = param2 __bjs_param2.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) @@ -1734,11 +1740,11 @@ extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { __bjs_param0.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(Int32(param1)) case .status(let param0, let param1, let param2): _swift_js_push_tag(Int32(2)) - _swift_js_push_int(param0 ? 1 : 0) - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(param0 ? 1 : 0) + _swift_js_push_i32(Int32(param1)) var __bjs_param2 = param2 __bjs_param2.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) @@ -1751,9 +1757,9 @@ extension API.NetworkingResult: _BridgedSwiftAssociatedValueEnum { private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> API.NetworkingResult { switch caseId { case 0: - return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .success(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 1: - return .failure(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + return .failure(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), Int.bridgeJSLiftParameter(_swift_js_pop_i32())) default: fatalError("Unknown API.NetworkingResult case ID: \(caseId)") } @@ -1774,7 +1780,7 @@ extension API.NetworkingResult: _BridgedSwiftAssociatedValueEnum { __bjs_param0.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(Int32(param1)) return Int32(1) } } @@ -1803,7 +1809,7 @@ extension API.NetworkingResult: _BridgedSwiftAssociatedValueEnum { __bjs_param0.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(param1)) + _swift_js_push_i32(Int32(param1)) } } } @@ -1812,11 +1818,11 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> APIOptionalResult { switch caseId { case 0: - return .success(Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .success(Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32(), _swift_js_pop_i32())) case 1: - return .failure(Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .failure(Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) case 2: - return .status(Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + return .status(Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()), Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32(), _swift_js_pop_i32())) default: fatalError("Unknown APIOptionalResult case ID: \(caseId)") } @@ -1834,31 +1840,31 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } } - _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + _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 { - _swift_js_push_int(Int32(__bjs_unwrapped_param0)) + _swift_js_push_i32(Int32(__bjs_unwrapped_param0)) } - _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) let __bjs_isSome_param1 = param1 != nil if let __bjs_unwrapped_param1 = param1 { - _swift_js_push_int(__bjs_unwrapped_param1 ? 1 : 0) + _swift_js_push_i32(__bjs_unwrapped_param1 ? 1 : 0) } - _swift_js_push_int(__bjs_isSome_param1 ? 1 : 0) + _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 { - _swift_js_push_int(__bjs_unwrapped_param0 ? 1 : 0) + _swift_js_push_i32(__bjs_unwrapped_param0 ? 1 : 0) } - _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) let __bjs_isSome_param1 = param1 != nil if let __bjs_unwrapped_param1 = param1 { - _swift_js_push_int(Int32(__bjs_unwrapped_param1)) + _swift_js_push_i32(Int32(__bjs_unwrapped_param1)) } - _swift_js_push_int(__bjs_isSome_param1 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) let __bjs_isSome_param2 = param2 != nil if let __bjs_unwrapped_param2 = param2 { var __bjs_str_param2 = __bjs_unwrapped_param2 @@ -1866,7 +1872,7 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } } - _swift_js_push_int(__bjs_isSome_param2 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param2 ? 1 : 0) return Int32(2) } } @@ -1892,31 +1898,31 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } } - _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) case .failure(let param0, let param1): _swift_js_push_tag(Int32(1)) let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - _swift_js_push_int(Int32(__bjs_unwrapped_param0)) + _swift_js_push_i32(Int32(__bjs_unwrapped_param0)) } - _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) let __bjs_isSome_param1 = param1 != nil if let __bjs_unwrapped_param1 = param1 { - _swift_js_push_int(__bjs_unwrapped_param1 ? 1 : 0) + _swift_js_push_i32(__bjs_unwrapped_param1 ? 1 : 0) } - _swift_js_push_int(__bjs_isSome_param1 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) case .status(let param0, let param1, let param2): _swift_js_push_tag(Int32(2)) let __bjs_isSome_param0 = param0 != nil if let __bjs_unwrapped_param0 = param0 { - _swift_js_push_int(__bjs_unwrapped_param0 ? 1 : 0) + _swift_js_push_i32(__bjs_unwrapped_param0 ? 1 : 0) } - _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) let __bjs_isSome_param1 = param1 != nil if let __bjs_unwrapped_param1 = param1 { - _swift_js_push_int(Int32(__bjs_unwrapped_param1)) + _swift_js_push_i32(Int32(__bjs_unwrapped_param1)) } - _swift_js_push_int(__bjs_isSome_param1 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) let __bjs_isSome_param2 = param2 != nil if let __bjs_unwrapped_param2 = param2 { var __bjs_str_param2 = __bjs_unwrapped_param2 @@ -1924,7 +1930,7 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } } - _swift_js_push_int(__bjs_isSome_param2 ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_param2 ? 1 : 0) } } } @@ -2212,13 +2218,120 @@ public func _bjs_StaticPropertyNamespace_NestedProperties_static_nestedDouble_se #endif } +extension Point: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> Point { + let y = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) + let x = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) + return Point(x: x, y: y) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { + _swift_js_push_i32(Int32(self.x)) + _swift_js_push_i32(Int32(self.y)) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Point())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Point") +fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_Point(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Point") +fileprivate func _bjs_struct_lift_Point() -> Int32 +#else +fileprivate func _bjs_struct_lift_Point() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +extension PointerFields: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> PointerFields { + let mutPtr = UnsafeMutablePointer.bridgeJSLiftParameter(_swift_js_pop_pointer()) + let ptr = UnsafePointer.bridgeJSLiftParameter(_swift_js_pop_pointer()) + let opaque = OpaquePointer.bridgeJSLiftParameter(_swift_js_pop_pointer()) + let mutRaw = UnsafeMutableRawPointer.bridgeJSLiftParameter(_swift_js_pop_pointer()) + let raw = UnsafeRawPointer.bridgeJSLiftParameter(_swift_js_pop_pointer()) + return PointerFields(raw: raw, mutRaw: mutRaw, opaque: opaque, ptr: ptr, mutPtr: mutPtr) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { + _swift_js_push_pointer(self.raw.bridgeJSLowerReturn()) + _swift_js_push_pointer(self.mutRaw.bridgeJSLowerReturn()) + _swift_js_push_pointer(self.opaque.bridgeJSLowerReturn()) + _swift_js_push_pointer(self.ptr.bridgeJSLowerReturn()) + _swift_js_push_pointer(self.mutPtr.bridgeJSLowerReturn()) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_PointerFields(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_PointerFields())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_PointerFields") +fileprivate func _bjs_struct_lower_PointerFields(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_PointerFields(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_PointerFields") +fileprivate func _bjs_struct_lift_PointerFields() -> Int32 +#else +fileprivate func _bjs_struct_lift_PointerFields() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_PointerFields_init") +@_cdecl("bjs_PointerFields_init") +public func _bjs_PointerFields_init(_ raw: UnsafeMutableRawPointer, _ mutRaw: UnsafeMutableRawPointer, _ opaque: UnsafeMutableRawPointer, _ ptr: UnsafeMutableRawPointer, _ mutPtr: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = PointerFields(raw: UnsafeRawPointer.bridgeJSLiftParameter(raw), mutRaw: UnsafeMutableRawPointer.bridgeJSLiftParameter(mutRaw), opaque: OpaquePointer.bridgeJSLiftParameter(opaque), ptr: UnsafePointer.bridgeJSLiftParameter(ptr), mutPtr: UnsafeMutablePointer.bridgeJSLiftParameter(mutPtr)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + extension DataPoint: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> DataPoint { - let optFlag = Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let optCount = Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let label = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let y = Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()) - let x = Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()) + let optFlag = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let optCount = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let label = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let y = Double.bridgeJSLiftParameter(_swift_js_pop_f64()) + let x = Double.bridgeJSLiftParameter(_swift_js_pop_f64()) return DataPoint(x: x, y: y, label: label, optCount: optCount, optFlag: optFlag) } @@ -2231,16 +2344,48 @@ extension DataPoint: _BridgedSwiftStruct { } let __bjs_isSome_optCount = self.optCount != nil if let __bjs_unwrapped_optCount = self.optCount { - _swift_js_push_int(Int32(__bjs_unwrapped_optCount)) + _swift_js_push_i32(Int32(__bjs_unwrapped_optCount)) } - _swift_js_push_int(__bjs_isSome_optCount ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_optCount ? 1 : 0) let __bjs_isSome_optFlag = self.optFlag != nil if let __bjs_unwrapped_optFlag = self.optFlag { - _swift_js_push_int(__bjs_unwrapped_optFlag ? 1 : 0) + _swift_js_push_i32(__bjs_unwrapped_optFlag ? 1 : 0) + } + _swift_js_push_i32(__bjs_isSome_optFlag ? 1 : 0) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_DataPoint(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) } - _swift_js_push_int(__bjs_isSome_optFlag ? 1 : 0) + self = Self.bridgeJSLiftParameter() } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_DataPoint())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_DataPoint") +fileprivate func _bjs_struct_lower_DataPoint(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_DataPoint(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_DataPoint") +fileprivate func _bjs_struct_lift_DataPoint() -> Int32 +#else +fileprivate func _bjs_struct_lift_DataPoint() -> Int32 { + fatalError("Only available on WebAssembly") } +#endif @_expose(wasm, "bjs_DataPoint_init") @_cdecl("bjs_DataPoint_init") @@ -2255,9 +2400,9 @@ public func _bjs_DataPoint_init(_ x: Float64, _ y: Float64, _ labelBytes: Int32, extension Address: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> Address { - let zipCode = Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let city = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let street = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) + let zipCode = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let city = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let street = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) return Address(street: street, city: city, zipCode: zipCode) } @@ -2272,19 +2417,51 @@ extension Address: _BridgedSwiftStruct { } let __bjs_isSome_zipCode = self.zipCode != nil if let __bjs_unwrapped_zipCode = self.zipCode { - _swift_js_push_int(Int32(__bjs_unwrapped_zipCode)) + _swift_js_push_i32(Int32(__bjs_unwrapped_zipCode)) + } + _swift_js_push_i32(__bjs_isSome_zipCode ? 1 : 0) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Address(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) } - _swift_js_push_int(__bjs_isSome_zipCode ? 1 : 0) + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Address())) } } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Address") +fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_Address(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Address") +fileprivate func _bjs_struct_lift_Address() -> Int32 +#else +fileprivate func _bjs_struct_lift_Address() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + extension Contact: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> Contact { - let secondaryAddress = Optional
.bridgeJSLiftParameter(_swift_js_pop_param_int32()) - let email = Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32(), _swift_js_pop_param_int32()) + let secondaryAddress = Optional
.bridgeJSLiftParameter(_swift_js_pop_i32()) + let email = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32(), _swift_js_pop_i32()) let address = Address.bridgeJSLiftParameter() - let age = Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()) - let name = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) + let age = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) + let name = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) return Contact(name: name, age: age, address: address, email: email, secondaryAddress: secondaryAddress) } @@ -2293,7 +2470,7 @@ extension Contact: _BridgedSwiftStruct { __bjs_name.withUTF8 { ptr in _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } - _swift_js_push_int(Int32(self.age)) + _swift_js_push_i32(Int32(self.age)) self.address.bridgeJSLowerReturn() let __bjs_isSome_email = self.email != nil if let __bjs_unwrapped_email = self.email { @@ -2302,21 +2479,53 @@ extension Contact: _BridgedSwiftStruct { _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } } - _swift_js_push_int(__bjs_isSome_email ? 1 : 0) + _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_int(__bjs_isSome_secondaryAddress ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_secondaryAddress ? 1 : 0) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Contact(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Contact())) } } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Contact") +fileprivate func _bjs_struct_lower_Contact(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_Contact(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Contact") +fileprivate func _bjs_struct_lift_Contact() -> Int32 +#else +fileprivate func _bjs_struct_lift_Contact() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + extension Config: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> Config { - let status = Status.bridgeJSLiftParameter(_swift_js_pop_param_int32()) - let direction = Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let theme = Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let name = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) + let status = Status.bridgeJSLiftParameter(_swift_js_pop_i32()) + let direction = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let theme = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32(), _swift_js_pop_i32()) + let name = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) return Config(name: name, theme: theme, direction: direction, status: status) } @@ -2332,68 +2541,336 @@ extension Config: _BridgedSwiftStruct { _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) } } - _swift_js_push_int(__bjs_isSome_theme ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_theme ? 1 : 0) let __bjs_isSome_direction = self.direction != nil if let __bjs_unwrapped_direction = self.direction { - _swift_js_push_int(__bjs_unwrapped_direction.bridgeJSLowerParameter()) + _swift_js_push_i32(__bjs_unwrapped_direction.bridgeJSLowerParameter()) } - _swift_js_push_int(__bjs_isSome_direction ? 1 : 0) - _swift_js_push_int(Int32(self.status.bridgeJSLowerParameter())) + _swift_js_push_i32(__bjs_isSome_direction ? 1 : 0) + _swift_js_push_i32(Int32(self.status.bridgeJSLowerParameter())) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Config(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Config())) } } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Config") +fileprivate func _bjs_struct_lower_Config(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_Config(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Config") +fileprivate func _bjs_struct_lift_Config() -> Int32 +#else +fileprivate func _bjs_struct_lift_Config() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + extension SessionData: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> SessionData { - let owner = Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_pointer()) - let id = Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()) + let owner = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_pointer()) + let id = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) return SessionData(id: id, owner: owner) } @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - _swift_js_push_int(Int32(self.id)) + _swift_js_push_i32(Int32(self.id)) let __bjs_isSome_owner = self.owner != nil if let __bjs_unwrapped_owner = self.owner { _swift_js_push_pointer(__bjs_unwrapped_owner.bridgeJSLowerReturn()) } - _swift_js_push_int(__bjs_isSome_owner ? 1 : 0) + _swift_js_push_i32(__bjs_isSome_owner ? 1 : 0) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_SessionData(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_SessionData())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_SessionData") +fileprivate func _bjs_struct_lower_SessionData(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_SessionData(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_SessionData") +fileprivate func _bjs_struct_lift_SessionData() -> Int32 +#else +fileprivate func _bjs_struct_lift_SessionData() -> Int32 { + fatalError("Only available on WebAssembly") } +#endif extension ValidationReport: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> ValidationReport { - let outcome = Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let status = Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - let result = APIResult.bridgeJSLiftParameter(_swift_js_pop_param_int32()) - let id = Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()) + let outcome = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let status = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let result = APIResult.bridgeJSLiftParameter(_swift_js_pop_i32()) + let id = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) return ValidationReport(id: id, result: result, status: status, outcome: outcome) } @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - _swift_js_push_int(Int32(self.id)) + _swift_js_push_i32(Int32(self.id)) self.result.bridgeJSLowerReturn() let __bjs_isSome_status = self.status != nil if let __bjs_unwrapped_status = self.status { - _swift_js_push_int(__bjs_unwrapped_status.bridgeJSLowerParameter()) + _swift_js_push_i32(__bjs_unwrapped_status.bridgeJSLowerParameter()) } - _swift_js_push_int(__bjs_isSome_status ? 1 : 0) + _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_int(__bjs_unwrapped_outcome.bridgeJSLowerParameter()) + _swift_js_push_i32(__bjs_unwrapped_outcome.bridgeJSLowerParameter()) + } + _swift_js_push_i32(__bjs_isSome_outcome ? 1 : 0) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_ValidationReport(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_ValidationReport())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_ValidationReport") +fileprivate func _bjs_struct_lower_ValidationReport(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_ValidationReport(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_ValidationReport") +fileprivate func _bjs_struct_lift_ValidationReport() -> Int32 +#else +fileprivate func _bjs_struct_lift_ValidationReport() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +extension AdvancedConfig: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> AdvancedConfig { + let overrideDefaults = Optional.bridgeJSLiftParameter(_swift_js_pop_i32()) + let defaults = ConfigStruct.bridgeJSLiftParameter() + let location = Optional.bridgeJSLiftParameter(_swift_js_pop_i32()) + let metadata = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let result = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let status = Status.bridgeJSLiftParameter(_swift_js_pop_i32()) + let theme = Theme.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let enabled = Bool.bridgeJSLiftParameter(_swift_js_pop_i32()) + let title = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + let id = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) + return AdvancedConfig(id: id, title: title, enabled: enabled, theme: theme, status: status, result: result, metadata: metadata, location: location, defaults: defaults, overrideDefaults: overrideDefaults) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { + _swift_js_push_i32(Int32(self.id)) + var __bjs_title = self.title + __bjs_title.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + _swift_js_push_i32(self.enabled ? 1 : 0) + var __bjs_theme = self.theme.rawValue + __bjs_theme.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + _swift_js_push_i32(Int32(self.status.bridgeJSLowerParameter())) + 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_isSome_result ? 1 : 0) + let __bjs_isSome_metadata = self.metadata != nil + if let __bjs_unwrapped_metadata = self.metadata { + _swift_js_push_i32(__bjs_unwrapped_metadata.bridgeJSLowerReturn()) + } + _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.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) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_AdvancedConfig(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_AdvancedConfig())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_AdvancedConfig") +fileprivate func _bjs_struct_lower_AdvancedConfig(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_AdvancedConfig(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_AdvancedConfig") +fileprivate func _bjs_struct_lift_AdvancedConfig() -> Int32 +#else +fileprivate func _bjs_struct_lift_AdvancedConfig() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +extension MeasurementConfig: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> MeasurementConfig { + let optionalRatio = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_f64()) + let optionalPrecision = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_f32()) + let ratio = Ratio.bridgeJSLiftParameter(_swift_js_pop_f64()) + let precision = Precision.bridgeJSLiftParameter(_swift_js_pop_f32()) + return MeasurementConfig(precision: precision, ratio: ratio, optionalPrecision: optionalPrecision, optionalRatio: optionalRatio) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { + _swift_js_push_f32(self.precision.bridgeJSLowerParameter()) + _swift_js_push_f64(self.ratio.bridgeJSLowerParameter()) + let __bjs_isSome_optionalPrecision = self.optionalPrecision != nil + if let __bjs_unwrapped_optionalPrecision = self.optionalPrecision { + _swift_js_push_f32(__bjs_unwrapped_optionalPrecision.bridgeJSLowerParameter()) + } + _swift_js_push_i32(__bjs_isSome_optionalPrecision ? 1 : 0) + let __bjs_isSome_optionalRatio = self.optionalRatio != nil + if let __bjs_unwrapped_optionalRatio = self.optionalRatio { + _swift_js_push_f64(__bjs_unwrapped_optionalRatio.bridgeJSLowerParameter()) + } + _swift_js_push_i32(__bjs_isSome_optionalRatio ? 1 : 0) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_MeasurementConfig(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) } - _swift_js_push_int(__bjs_isSome_outcome ? 1 : 0) + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_MeasurementConfig())) } } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_MeasurementConfig") +fileprivate func _bjs_struct_lower_MeasurementConfig(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_MeasurementConfig(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_MeasurementConfig") +fileprivate func _bjs_struct_lift_MeasurementConfig() -> Int32 +#else +fileprivate func _bjs_struct_lift_MeasurementConfig() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + extension MathOperations: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> MathOperations { - let baseValue = Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()) + let baseValue = Double.bridgeJSLiftParameter(_swift_js_pop_f64()) return MathOperations(baseValue: baseValue) } @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { _swift_js_push_f64(self.baseValue) } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_MathOperations(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_MathOperations())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_MathOperations") +fileprivate func _bjs_struct_lower_MathOperations(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_MathOperations(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_MathOperations") +fileprivate func _bjs_struct_lift_MathOperations() -> Int32 +#else +fileprivate func _bjs_struct_lift_MathOperations() -> Int32 { + fatalError("Only available on WebAssembly") } +#endif @_expose(wasm, "bjs_MathOperations_init") @_cdecl("bjs_MathOperations_init") @@ -2439,31 +2916,236 @@ public func _bjs_MathOperations_static_subtract(_ a: Float64, _ b: Float64) -> F #endif } -extension ConfigStruct: _BridgedSwiftStruct { - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> ConfigStruct { - let value = Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()) - let name = String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) - return ConfigStruct(name: name, value: value) +extension CopyableCart: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> CopyableCart { + let note = Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32(), _swift_js_pop_i32()) + let x = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) + return CopyableCart(x: x, note: note) } @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { - var __bjs_name = self.name - __bjs_name.withUTF8 { ptr in - _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + _swift_js_push_i32(Int32(self.x)) + let __bjs_isSome_note = self.note != nil + if let __bjs_unwrapped_note = self.note { + var __bjs_str_note = __bjs_unwrapped_note + __bjs_str_note.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } } - _swift_js_push_int(Int32(self.value)) + _swift_js_push_i32(__bjs_isSome_note ? 1 : 0) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_CopyableCart(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_CopyableCart())) } } -@_expose(wasm, "bjs_ConfigStruct_static_defaultConfig_get") -@_cdecl("bjs_ConfigStruct_static_defaultConfig_get") -public func _bjs_ConfigStruct_static_defaultConfig_get() -> Void { - #if arch(wasm32) - let ret = ConfigStruct.defaultConfig - return ret.bridgeJSLowerReturn() - #else +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_CopyableCart") +fileprivate func _bjs_struct_lower_CopyableCart(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_CopyableCart(_ objectId: Int32) -> Int32 { fatalError("Only available on WebAssembly") - #endif +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_CopyableCart") +fileprivate func _bjs_struct_lift_CopyableCart() -> Int32 +#else +fileprivate func _bjs_struct_lift_CopyableCart() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_CopyableCart_static_fromJSObject") +@_cdecl("bjs_CopyableCart_static_fromJSObject") +public func _bjs_CopyableCart_static_fromJSObject(_ object: Int32) -> Void { + #if arch(wasm32) + let ret = CopyableCart.fromJSObject(_: JSObject.bridgeJSLiftParameter(object)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension CopyableCartItem: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> CopyableCartItem { + let quantity = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) + let sku = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + return CopyableCartItem(sku: sku, quantity: quantity) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { + var __bjs_sku = self.sku + __bjs_sku.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + _swift_js_push_i32(Int32(self.quantity)) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_CopyableCartItem(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_CopyableCartItem())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_CopyableCartItem") +fileprivate func _bjs_struct_lower_CopyableCartItem(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_CopyableCartItem(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_CopyableCartItem") +fileprivate func _bjs_struct_lift_CopyableCartItem() -> Int32 +#else +fileprivate func _bjs_struct_lift_CopyableCartItem() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +extension CopyableNestedCart: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> CopyableNestedCart { + let shippingAddress = Optional
.bridgeJSLiftParameter(_swift_js_pop_i32()) + let item = CopyableCartItem.bridgeJSLiftParameter() + let id = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) + return CopyableNestedCart(id: id, item: item, shippingAddress: shippingAddress) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { + _swift_js_push_i32(Int32(self.id)) + 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) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_CopyableNestedCart(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_CopyableNestedCart())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_CopyableNestedCart") +fileprivate func _bjs_struct_lower_CopyableNestedCart(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_CopyableNestedCart(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_CopyableNestedCart") +fileprivate func _bjs_struct_lift_CopyableNestedCart() -> Int32 +#else +fileprivate func _bjs_struct_lift_CopyableNestedCart() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_CopyableNestedCart_static_fromJSObject") +@_cdecl("bjs_CopyableNestedCart_static_fromJSObject") +public func _bjs_CopyableNestedCart_static_fromJSObject(_ object: Int32) -> Void { + #if arch(wasm32) + let ret = CopyableNestedCart.fromJSObject(_: JSObject.bridgeJSLiftParameter(object)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension ConfigStruct: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter() -> ConfigStruct { + let value = Int.bridgeJSLiftParameter(_swift_js_pop_i32()) + let name = String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32()) + return ConfigStruct(name: name, value: value) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { + var __bjs_name = self.name + __bjs_name.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + _swift_js_push_i32(Int32(self.value)) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_ConfigStruct(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSLiftParameter() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSLowerReturn() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_ConfigStruct())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_ConfigStruct") +fileprivate func _bjs_struct_lower_ConfigStruct(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_ConfigStruct(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_ConfigStruct") +fileprivate func _bjs_struct_lift_ConfigStruct() -> Int32 +#else +fileprivate func _bjs_struct_lift_ConfigStruct() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_ConfigStruct_static_defaultConfig_get") +@_cdecl("bjs_ConfigStruct_static_defaultConfig_get") +public func _bjs_ConfigStruct_static_defaultConfig_get() -> Void { + #if arch(wasm32) + let ret = ConfigStruct.defaultConfig + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif } @_expose(wasm, "bjs_ConfigStruct_static_defaultConfig_set") @@ -2540,6 +3222,17 @@ public func _bjs_roundTripInt(_ v: Int32) -> Int32 { #endif } +@_expose(wasm, "bjs_roundTripUInt") +@_cdecl("bjs_roundTripUInt") +public func _bjs_roundTripUInt(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundTripUInt(v: UInt.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_roundTripFloat") @_cdecl("bjs_roundTripFloat") public func _bjs_roundTripFloat(_ v: Float32) -> Float32 { @@ -2595,6 +3288,61 @@ public func _bjs_roundTripSwiftHeapObject(_ v: UnsafeMutableRawPointer) -> Unsaf #endif } +@_expose(wasm, "bjs_roundTripUnsafeRawPointer") +@_cdecl("bjs_roundTripUnsafeRawPointer") +public func _bjs_roundTripUnsafeRawPointer(_ v: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = roundTripUnsafeRawPointer(v: UnsafeRawPointer.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripUnsafeMutableRawPointer") +@_cdecl("bjs_roundTripUnsafeMutableRawPointer") +public func _bjs_roundTripUnsafeMutableRawPointer(_ v: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = roundTripUnsafeMutableRawPointer(v: UnsafeMutableRawPointer.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOpaquePointer") +@_cdecl("bjs_roundTripOpaquePointer") +public func _bjs_roundTripOpaquePointer(_ v: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = roundTripOpaquePointer(v: OpaquePointer.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripUnsafePointer") +@_cdecl("bjs_roundTripUnsafePointer") +public func _bjs_roundTripUnsafePointer(_ v: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = roundTripUnsafePointer(v: UnsafePointer.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripUnsafeMutablePointer") +@_cdecl("bjs_roundTripUnsafeMutablePointer") +public func _bjs_roundTripUnsafeMutablePointer(_ v: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = roundTripUnsafeMutablePointer(v: UnsafeMutablePointer.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_roundTripJSObject") @_cdecl("bjs_roundTripJSObject") public func _bjs_roundTripJSObject(_ v: Int32) -> Int32 { @@ -3759,99 +4507,990 @@ public func _bjs_testMultipleDefaults(_ titleBytes: Int32, _ titleLength: Int32, #endif } -@_expose(wasm, "bjs_testSimpleEnumDefault") -@_cdecl("bjs_testSimpleEnumDefault") -public func _bjs_testSimpleEnumDefault(_ status: Int32) -> Int32 { +@_expose(wasm, "bjs_testSimpleEnumDefault") +@_cdecl("bjs_testSimpleEnumDefault") +public func _bjs_testSimpleEnumDefault(_ status: Int32) -> Int32 { + #if arch(wasm32) + let ret = testSimpleEnumDefault(status: Status.bridgeJSLiftParameter(status)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testDirectionDefault") +@_cdecl("bjs_testDirectionDefault") +public func _bjs_testDirectionDefault(_ direction: Int32) -> Int32 { + #if arch(wasm32) + let ret = testDirectionDefault(direction: Direction.bridgeJSLiftParameter(direction)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testRawStringEnumDefault") +@_cdecl("bjs_testRawStringEnumDefault") +public func _bjs_testRawStringEnumDefault(_ themeBytes: Int32, _ themeLength: Int32) -> Void { + #if arch(wasm32) + let ret = testRawStringEnumDefault(theme: Theme.bridgeJSLiftParameter(themeBytes, themeLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testComplexInit") +@_cdecl("bjs_testComplexInit") +public func _bjs_testComplexInit(_ greeter: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = testComplexInit(greeter: Greeter.bridgeJSLiftParameter(greeter)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testEmptyInit") +@_cdecl("bjs_testEmptyInit") +public func _bjs_testEmptyInit(_ object: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = testEmptyInit(_: StaticPropertyHolder.bridgeJSLiftParameter(object)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_arrayWithDefault") +@_cdecl("bjs_arrayWithDefault") +public func _bjs_arrayWithDefault() -> Int32 { + #if arch(wasm32) + let ret = arrayWithDefault(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_arrayWithOptionalDefault") +@_cdecl("bjs_arrayWithOptionalDefault") +public func _bjs_arrayWithOptionalDefault(_ values: Int32) -> Int32 { + #if arch(wasm32) + let ret = arrayWithOptionalDefault(_: { + if values == 0 { + return Optional<[Int]>.none + } else { + return { + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }() + } + }()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_arrayMixedDefaults") +@_cdecl("bjs_arrayMixedDefaults") +public func _bjs_arrayMixedDefaults(_ prefixBytes: Int32, _ prefixLength: Int32, _ suffixBytes: Int32, _ suffixLength: Int32) -> Void { + #if arch(wasm32) + let ret = arrayMixedDefaults(prefix: String.bridgeJSLiftParameter(prefixBytes, prefixLength), values: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }(), suffix: String.bridgeJSLiftParameter(suffixBytes, suffixLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_formatName") +@_cdecl("bjs_formatName") +public func _bjs_formatName(_ nameBytes: Int32, _ nameLength: Int32, _ transform: Int32) -> Void { + #if arch(wasm32) + let ret = formatName(_: String.bridgeJSLiftParameter(nameBytes, nameLength), transform: _BJS_Closure_20BridgeJSRuntimeTestsSS_SS.bridgeJSLift(transform)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeFormatter") +@_cdecl("bjs_makeFormatter") +public func _bjs_makeFormatter(_ prefixBytes: Int32, _ prefixLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = makeFormatter(prefix: String.bridgeJSLiftParameter(prefixBytes, prefixLength)) + return _BJS_Closure_20BridgeJSRuntimeTestsSS_SS.bridgeJSLower(ret) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAdder") +@_cdecl("bjs_makeAdder") +public func _bjs_makeAdder(_ base: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = makeAdder(base: Int.bridgeJSLiftParameter(base)) + return _BJS_Closure_20BridgeJSRuntimeTestsSi_Si.bridgeJSLower(ret) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripIntArray") +@_cdecl("bjs_roundTripIntArray") +public func _bjs_roundTripIntArray() -> Void { + #if arch(wasm32) + let ret = roundTripIntArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_i32(Int32(__bjs_elem_ret))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripStringArray") +@_cdecl("bjs_roundTripStringArray") +public func _bjs_roundTripStringArray() -> Void { + #if arch(wasm32) + let ret = roundTripStringArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [String] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + var __bjs_ret_elem = __bjs_elem_ret + __bjs_ret_elem.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + }} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripDoubleArray") +@_cdecl("bjs_roundTripDoubleArray") +public func _bjs_roundTripDoubleArray() -> Void { + #if arch(wasm32) + let ret = roundTripDoubleArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Double] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Double.bridgeJSLiftParameter(_swift_js_pop_f64())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_f64(__bjs_elem_ret)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripBoolArray") +@_cdecl("bjs_roundTripBoolArray") +public func _bjs_roundTripBoolArray() -> Void { + #if arch(wasm32) + let ret = roundTripBoolArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Bool] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Bool.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_i32(__bjs_elem_ret ? 1 : 0)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripDirectionArray") +@_cdecl("bjs_roundTripDirectionArray") +public func _bjs_roundTripDirectionArray() -> Void { + #if arch(wasm32) + let ret = roundTripDirectionArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Direction] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Direction.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_i32(Int32(__bjs_elem_ret.bridgeJSLowerParameter()))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripStatusArray") +@_cdecl("bjs_roundTripStatusArray") +public func _bjs_roundTripStatusArray() -> Void { + #if arch(wasm32) + let ret = roundTripStatusArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Status] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Status.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_i32(Int32(__bjs_elem_ret.bridgeJSLowerParameter()))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripThemeArray") +@_cdecl("bjs_roundTripThemeArray") +public func _bjs_roundTripThemeArray() -> Void { + #if arch(wasm32) + let ret = roundTripThemeArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Theme] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Theme.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + var __bjs_ret_elem = __bjs_elem_ret.rawValue + __bjs_ret_elem.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + }} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripHttpStatusArray") +@_cdecl("bjs_roundTripHttpStatusArray") +public func _bjs_roundTripHttpStatusArray() -> Void { + #if arch(wasm32) + let ret = roundTripHttpStatusArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [HttpStatus] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(HttpStatus.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_i32(Int32(__bjs_elem_ret.bridgeJSLowerParameter()))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripDataPointArray") +@_cdecl("bjs_roundTripDataPointArray") +public func _bjs_roundTripDataPointArray() -> Void { + #if arch(wasm32) + let ret = roundTripDataPointArray(_: { + 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)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripGreeterArray") +@_cdecl("bjs_roundTripGreeterArray") +public func _bjs_roundTripGreeterArray() -> Void { + #if arch(wasm32) + let ret = roundTripGreeterArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Greeter] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Greeter.bridgeJSLiftParameter(_swift_js_pop_pointer())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_pointer(__bjs_elem_ret.bridgeJSLowerReturn())} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalIntArray") +@_cdecl("bjs_roundTripOptionalIntArray") +public func _bjs_roundTripOptionalIntArray() -> Void { + #if arch(wasm32) + let ret = roundTripOptionalIntArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __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 { + _swift_js_push_i32(Int32(__bjs_unwrapped_ret_elem))} + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalStringArray") +@_cdecl("bjs_roundTripOptionalStringArray") +public func _bjs_roundTripOptionalStringArray() -> Void { + #if arch(wasm32) + let ret = roundTripOptionalStringArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32(), _swift_js_pop_i32())) + } + __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 { + var __bjs_str_ret_elem = __bjs_unwrapped_ret_elem + __bjs_str_ret_elem.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + }} + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalDataPointArray") +@_cdecl("bjs_roundTripOptionalDataPointArray") +public func _bjs_roundTripOptionalDataPointArray() -> Void { + #if arch(wasm32) + let ret = roundTripOptionalDataPointArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Optional.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __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)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalDirectionArray") +@_cdecl("bjs_roundTripOptionalDirectionArray") +public func _bjs_roundTripOptionalDirectionArray() -> Void { + #if arch(wasm32) + let ret = roundTripOptionalDirectionArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __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 { + _swift_js_push_i32(__bjs_unwrapped_ret_elem.bridgeJSLowerParameter())} + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalStatusArray") +@_cdecl("bjs_roundTripOptionalStatusArray") +public func _bjs_roundTripOptionalStatusArray() -> Void { + #if arch(wasm32) + let ret = roundTripOptionalStatusArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Optional.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __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 { + _swift_js_push_i32(__bjs_unwrapped_ret_elem.bridgeJSLowerParameter())} + _swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalIntArrayType") +@_cdecl("bjs_roundTripOptionalIntArrayType") +public func _bjs_roundTripOptionalIntArrayType(_ values: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalIntArrayType(_: { + if values == 0 { + return Optional<[Int]>.none + } else { + return { + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }() + } + }()) + let __bjs_isSome_ret = ret != nil + if let __bjs_unwrapped_ret = ret { + for __bjs_elem_ret in __bjs_unwrapped_ret { + _swift_js_push_i32(Int32(__bjs_elem_ret))} + _swift_js_push_i32(Int32(__bjs_unwrapped_ret.count))} + _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalStringArrayType") +@_cdecl("bjs_roundTripOptionalStringArrayType") +public func _bjs_roundTripOptionalStringArrayType(_ values: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalStringArrayType(_: { + if values == 0 { + return Optional<[String]>.none + } else { + return { + let __count = Int(_swift_js_pop_i32()) + var __result: [String] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __result.reverse() + return __result + }() + } + }()) + let __bjs_isSome_ret = ret != nil + if let __bjs_unwrapped_ret = ret { + for __bjs_elem_ret in __bjs_unwrapped_ret { + var __bjs_ret_elem = __bjs_elem_ret + __bjs_ret_elem.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + }} + _swift_js_push_i32(Int32(__bjs_unwrapped_ret.count))} + _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalGreeterArrayType") +@_cdecl("bjs_roundTripOptionalGreeterArrayType") +public func _bjs_roundTripOptionalGreeterArrayType(_ greeters: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalGreeterArrayType(_: { + if greeters == 0 { + return Optional<[Greeter]>.none + } else { + return { + let __count = Int(_swift_js_pop_i32()) + var __result: [Greeter] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Greeter.bridgeJSLiftParameter(_swift_js_pop_pointer())) + } + __result.reverse() + return __result + }() + } + }()) + let __bjs_isSome_ret = ret != nil + if let __bjs_unwrapped_ret = ret { + for __bjs_elem_ret in __bjs_unwrapped_ret { + _swift_js_push_pointer(__bjs_elem_ret.bridgeJSLowerReturn())} + _swift_js_push_i32(Int32(__bjs_unwrapped_ret.count))} + _swift_js_push_i32(__bjs_isSome_ret ? 1 : 0) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripNestedIntArray") +@_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({ + let __count = Int(_swift_js_pop_i32()) + var __result: [Int] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Int.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + for __bjs_elem_ret_elem in __bjs_elem_ret { + _swift_js_push_i32(Int32(__bjs_elem_ret_elem))} + _swift_js_push_i32(Int32(__bjs_elem_ret.count))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripNestedStringArray") +@_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({ + let __count = Int(_swift_js_pop_i32()) + var __result: [String] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + for __bjs_elem_ret_elem in __bjs_elem_ret { + var __bjs_ret_elem_elem = __bjs_elem_ret_elem + __bjs_ret_elem_elem.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + }} + _swift_js_push_i32(Int32(__bjs_elem_ret.count))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripNestedDoubleArray") +@_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({ + let __count = Int(_swift_js_pop_i32()) + var __result: [Double] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Double.bridgeJSLiftParameter(_swift_js_pop_f64())) + } + __result.reverse() + return __result + }()) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + for __bjs_elem_ret_elem in __bjs_elem_ret { + _swift_js_push_f64(__bjs_elem_ret_elem)} + _swift_js_push_i32(Int32(__bjs_elem_ret.count))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripNestedBoolArray") +@_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({ + let __count = Int(_swift_js_pop_i32()) + var __result: [Bool] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Bool.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + for __bjs_elem_ret_elem in __bjs_elem_ret { + _swift_js_push_i32(__bjs_elem_ret_elem ? 1 : 0)} + _swift_js_push_i32(Int32(__bjs_elem_ret.count))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripNestedDataPointArray") +@_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({ + 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 + }()) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + for __bjs_elem_ret_elem in __bjs_elem_ret { + __bjs_elem_ret_elem.bridgeJSLowerReturn()} + _swift_js_push_i32(Int32(__bjs_elem_ret.count))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripNestedDirectionArray") +@_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({ + let __count = Int(_swift_js_pop_i32()) + var __result: [Direction] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Direction.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + for __bjs_elem_ret_elem in __bjs_elem_ret { + _swift_js_push_i32(Int32(__bjs_elem_ret_elem.bridgeJSLowerParameter()))} + _swift_js_push_i32(Int32(__bjs_elem_ret.count))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripNestedGreeterArray") +@_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({ + let __count = Int(_swift_js_pop_i32()) + var __result: [Greeter] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(Greeter.bridgeJSLiftParameter(_swift_js_pop_pointer())) + } + __result.reverse() + return __result + }()) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + for __bjs_elem_ret_elem in __bjs_elem_ret { + _swift_js_push_pointer(__bjs_elem_ret_elem.bridgeJSLowerReturn())} + _swift_js_push_i32(Int32(__bjs_elem_ret.count))} + _swift_js_push_i32(Int32(ret.count)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripUnsafeRawPointerArray") +@_cdecl("bjs_roundTripUnsafeRawPointerArray") +public func _bjs_roundTripUnsafeRawPointerArray() -> Void { #if arch(wasm32) - let ret = testSimpleEnumDefault(status: Status.bridgeJSLiftParameter(status)) - return ret.bridgeJSLowerReturn() + let ret = roundTripUnsafeRawPointerArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [UnsafeRawPointer] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(UnsafeRawPointer.bridgeJSLiftParameter(_swift_js_pop_pointer())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_pointer(__bjs_elem_ret.bridgeJSLowerReturn())} + _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_testDirectionDefault") -@_cdecl("bjs_testDirectionDefault") -public func _bjs_testDirectionDefault(_ direction: Int32) -> Int32 { +@_expose(wasm, "bjs_roundTripUnsafeMutableRawPointerArray") +@_cdecl("bjs_roundTripUnsafeMutableRawPointerArray") +public func _bjs_roundTripUnsafeMutableRawPointerArray() -> Void { #if arch(wasm32) - let ret = testDirectionDefault(direction: Direction.bridgeJSLiftParameter(direction)) - return ret.bridgeJSLowerReturn() + let ret = roundTripUnsafeMutableRawPointerArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [UnsafeMutableRawPointer] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(UnsafeMutableRawPointer.bridgeJSLiftParameter(_swift_js_pop_pointer())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_pointer(__bjs_elem_ret.bridgeJSLowerReturn())} + _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_testRawStringEnumDefault") -@_cdecl("bjs_testRawStringEnumDefault") -public func _bjs_testRawStringEnumDefault(_ themeBytes: Int32, _ themeLength: Int32) -> Void { +@_expose(wasm, "bjs_roundTripOpaquePointerArray") +@_cdecl("bjs_roundTripOpaquePointerArray") +public func _bjs_roundTripOpaquePointerArray() -> Void { #if arch(wasm32) - let ret = testRawStringEnumDefault(theme: Theme.bridgeJSLiftParameter(themeBytes, themeLength)) - return ret.bridgeJSLowerReturn() + let ret = roundTripOpaquePointerArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [OpaquePointer] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(OpaquePointer.bridgeJSLiftParameter(_swift_js_pop_pointer())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_pointer(__bjs_elem_ret.bridgeJSLowerReturn())} + _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_testComplexInit") -@_cdecl("bjs_testComplexInit") -public func _bjs_testComplexInit(_ greeter: UnsafeMutableRawPointer) -> Void { +@_expose(wasm, "bjs_consumeDataProcessorArrayType") +@_cdecl("bjs_consumeDataProcessorArrayType") +public func _bjs_consumeDataProcessorArrayType() -> Int32 { #if arch(wasm32) - let ret = testComplexInit(greeter: Greeter.bridgeJSLiftParameter(greeter)) + let ret = consumeDataProcessorArrayType(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [AnyDataProcessor] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(AnyDataProcessor.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_testEmptyInit") -@_cdecl("bjs_testEmptyInit") -public func _bjs_testEmptyInit(_ object: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { +@_expose(wasm, "bjs_roundTripDataProcessorArrayType") +@_cdecl("bjs_roundTripDataProcessorArrayType") +public func _bjs_roundTripDataProcessorArrayType() -> Void { #if arch(wasm32) - let ret = testEmptyInit(_: StaticPropertyHolder.bridgeJSLiftParameter(object)) - return ret.bridgeJSLowerReturn() + let ret = roundTripDataProcessorArrayType(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [AnyDataProcessor] = [] + __result.reserveCapacity(__count) + for _ in 0 ..< __count { + __result.append(AnyDataProcessor.bridgeJSLiftParameter(_swift_js_pop_i32())) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + _swift_js_push_i32((__bjs_elem_ret as! AnyDataProcessor).bridgeJSLowerReturn())} + _swift_js_push_i32(Int32(ret.count)) #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_formatName") -@_cdecl("bjs_formatName") -public func _bjs_formatName(_ nameBytes: Int32, _ nameLength: Int32, _ transform: Int32) -> Void { +@_expose(wasm, "bjs_roundTripPointerFields") +@_cdecl("bjs_roundTripPointerFields") +public func _bjs_roundTripPointerFields() -> Void { #if arch(wasm32) - let ret = formatName(_: String.bridgeJSLiftParameter(nameBytes, nameLength), transform: _BJS_Closure_20BridgeJSRuntimeTestsSS_SS.bridgeJSLift(transform)) + let ret = roundTripPointerFields(_: PointerFields.bridgeJSLiftParameter()) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_makeFormatter") -@_cdecl("bjs_makeFormatter") -public func _bjs_makeFormatter(_ prefixBytes: Int32, _ prefixLength: Int32) -> UnsafeMutableRawPointer { +@_expose(wasm, "bjs_testStructDefault") +@_cdecl("bjs_testStructDefault") +public func _bjs_testStructDefault() -> Void { #if arch(wasm32) - let ret = makeFormatter(prefix: String.bridgeJSLiftParameter(prefixBytes, prefixLength)) - return _BJS_Closure_20BridgeJSRuntimeTestsSS_SS.bridgeJSLower(ret) + let ret = testStructDefault(point: DataPoint.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_makeAdder") -@_cdecl("bjs_makeAdder") -public func _bjs_makeAdder(_ base: Int32) -> UnsafeMutableRawPointer { +@_expose(wasm, "bjs_cartToJSObject") +@_cdecl("bjs_cartToJSObject") +public func _bjs_cartToJSObject() -> Int32 { #if arch(wasm32) - let ret = makeAdder(base: Int.bridgeJSLiftParameter(base)) - return _BJS_Closure_20BridgeJSRuntimeTestsSi_Si.bridgeJSLower(ret) + let ret = cartToJSObject(_: CopyableCart.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_testStructDefault") -@_cdecl("bjs_testStructDefault") -public func _bjs_testStructDefault() -> Void { +@_expose(wasm, "bjs_nestedCartToJSObject") +@_cdecl("bjs_nestedCartToJSObject") +public func _bjs_nestedCartToJSObject() -> Int32 { #if arch(wasm32) - let ret = testStructDefault(point: DataPoint.bridgeJSLiftParameter()) + let ret = nestedCartToJSObject(_: CopyableNestedCart.bridgeJSLiftParameter()) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -3913,6 +5552,28 @@ public func _bjs_roundTripValidationReport() -> Void { #endif } +@_expose(wasm, "bjs_roundTripAdvancedConfig") +@_cdecl("bjs_roundTripAdvancedConfig") +public func _bjs_roundTripAdvancedConfig() -> Void { + #if arch(wasm32) + let ret = roundTripAdvancedConfig(_: AdvancedConfig.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripMeasurementConfig") +@_cdecl("bjs_roundTripMeasurementConfig") +public func _bjs_roundTripMeasurementConfig() -> Void { + #if arch(wasm32) + let ret = roundTripMeasurementConfig(_: MeasurementConfig.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_updateValidationReport") @_cdecl("bjs_updateValidationReport") public func _bjs_updateValidationReport(_ newResultIsSome: Int32, _ newResultCaseId: Int32) -> Void { @@ -6273,6 +7934,23 @@ func _$Foo_value_get(_ self: JSObject) throws(JSException) -> String { return String.bridgeJSLiftReturn(ret) } +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_globalObject1_get") +fileprivate func bjs_globalObject1_get() -> Int32 +#else +fileprivate func bjs_globalObject1_get() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$globalObject1_get() throws(JSException) -> JSObject { + let ret = bjs_globalObject1_get() + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripVoid") fileprivate func bjs_jsRoundTripVoid() -> Void @@ -6449,6 +8127,41 @@ func _$runAsyncWorks() throws(JSException) -> JSPromise { return JSPromise.bridgeJSLiftReturn(ret) } +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs__jsWeirdFunction") +fileprivate func bjs__jsWeirdFunction() -> Float64 +#else +fileprivate func bjs__jsWeirdFunction() -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$_jsWeirdFunction() throws(JSException) -> Double { + let ret = bjs__jsWeirdFunction() + if let error = _swift_js_take_exception() { + throw error + } + return Double.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_parseInt") +fileprivate func bjs_parseInt(_ string: Int32) -> Float64 +#else +fileprivate func bjs_parseInt(_ string: Int32) -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$parseInt(_ string: String) throws(JSException) -> Double { + let stringValue = string.bridgeJSLowerParameter() + let ret = bjs_parseInt(stringValue) + if let error = _swift_js_take_exception() { + throw error + } + return Double.bridgeJSLiftReturn(ret) +} + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JsGreeter_init") fileprivate func bjs_JsGreeter_init(_ name: Int32, _ prefix: Int32) -> Int32 @@ -6558,6 +8271,205 @@ func _$JsGreeter_changeName(_ self: JSObject, _ name: String) throws(JSException } } +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs__WeirdClass_init") +fileprivate func bjs__WeirdClass_init() -> Int32 +#else +fileprivate func bjs__WeirdClass_init() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs__WeirdClass_method_with_dashes") +fileprivate func bjs__WeirdClass_method_with_dashes(_ self: Int32) -> Int32 +#else +fileprivate func bjs__WeirdClass_method_with_dashes(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$_WeirdClass_init() throws(JSException) -> JSObject { + let ret = bjs__WeirdClass_init() + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + +func _$_WeirdClass_method_with_dashes(_ self: JSObject) throws(JSException) -> String { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs__WeirdClass_method_with_dashes(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Animal_init") +fileprivate func bjs_Animal_init(_ name: Int32, _ age: Float64, _ isCat: Int32) -> Int32 +#else +fileprivate func bjs_Animal_init(_ name: Int32, _ age: Float64, _ isCat: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Animal_name_get") +fileprivate func bjs_Animal_name_get(_ self: Int32) -> Int32 +#else +fileprivate func bjs_Animal_name_get(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Animal_age_get") +fileprivate func bjs_Animal_age_get(_ self: Int32) -> Float64 +#else +fileprivate func bjs_Animal_age_get(_ self: Int32) -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Animal_isCat_get") +fileprivate func bjs_Animal_isCat_get(_ self: Int32) -> Int32 +#else +fileprivate func bjs_Animal_isCat_get(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Animal_name_set") +fileprivate func bjs_Animal_name_set(_ self: Int32, _ newValue: Int32) -> Void +#else +fileprivate func bjs_Animal_name_set(_ self: Int32, _ newValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Animal_age_set") +fileprivate func bjs_Animal_age_set(_ self: Int32, _ newValue: Float64) -> Void +#else +fileprivate func bjs_Animal_age_set(_ self: Int32, _ newValue: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Animal_isCat_set") +fileprivate func bjs_Animal_isCat_set(_ self: Int32, _ newValue: Int32) -> Void +#else +fileprivate func bjs_Animal_isCat_set(_ self: Int32, _ newValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Animal_bark") +fileprivate func bjs_Animal_bark(_ self: Int32) -> Int32 +#else +fileprivate func bjs_Animal_bark(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Animal_getIsCat") +fileprivate func bjs_Animal_getIsCat(_ self: Int32) -> Int32 +#else +fileprivate func bjs_Animal_getIsCat(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$Animal_init(_ name: String, _ age: Double, _ isCat: Bool) throws(JSException) -> JSObject { + let nameValue = name.bridgeJSLowerParameter() + let ageValue = age.bridgeJSLowerParameter() + let isCatValue = isCat.bridgeJSLowerParameter() + let ret = bjs_Animal_init(nameValue, ageValue, isCatValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + +func _$Animal_name_get(_ self: JSObject) throws(JSException) -> String { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_Animal_name_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +func _$Animal_age_get(_ self: JSObject) throws(JSException) -> Double { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_Animal_age_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return Double.bridgeJSLiftReturn(ret) +} + +func _$Animal_isCat_get(_ self: JSObject) throws(JSException) -> Bool { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_Animal_isCat_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return Bool.bridgeJSLiftReturn(ret) +} + +func _$Animal_name_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_Animal_name_set(selfValue, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$Animal_age_set(_ self: JSObject, _ newValue: Double) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_Animal_age_set(selfValue, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$Animal_isCat_set(_ self: JSObject, _ newValue: Bool) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_Animal_isCat_set(selfValue, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$Animal_bark(_ self: JSObject) throws(JSException) -> String { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_Animal_bark(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +func _$Animal_getIsCat(_ self: JSObject) throws(JSException) -> Bool { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_Animal_getIsCat(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return Bool.bridgeJSLiftReturn(ret) +} + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsApplyInt") fileprivate func bjs_jsApplyInt(_ value: Int32, _ transform: UnsafeMutableRawPointer) -> Int32 @@ -6649,4 +8561,24 @@ func _$jsCallTwice(_ value: Int, _ callback: @escaping (Int) -> Void) throws(JSE throw error } return Int.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsTranslatePoint") +fileprivate func bjs_jsTranslatePoint(_ point: Int32, _ dx: Int32, _ dy: Int32) -> Int32 +#else +fileprivate func bjs_jsTranslatePoint(_ point: Int32, _ dx: Int32, _ dy: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsTranslatePoint(_ point: Point, _ dx: Int, _ dy: Int) throws(JSException) -> Point { + let pointObjectId = point.bridgeJSLowerParameter() + let dxValue = dx.bridgeJSLowerParameter() + let dyValue = dy.bridgeJSLowerParameter() + let ret = bjs_jsTranslatePoint(pointObjectId, dxValue, dyValue) + if let error = _swift_js_take_exception() { + throw error + } + return Point.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 66a87b063..c79139ea4 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json @@ -3341,6 +3341,78 @@ { "associatedValues" : [ + ], + "name" : "rough", + "rawValue" : "0.1" + }, + { + "associatedValues" : [ + + ], + "name" : "normal", + "rawValue" : "0.01" + }, + { + "associatedValues" : [ + + ], + "name" : "fine", + "rawValue" : "0.001" + } + ], + "emitStyle" : "const", + "name" : "Precision", + "rawType" : "Float", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Precision", + "tsFullPath" : "Precision" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "quarter", + "rawValue" : "0.25" + }, + { + "associatedValues" : [ + + ], + "name" : "half", + "rawValue" : "0.5" + }, + { + "associatedValues" : [ + + ], + "name" : "golden", + "rawValue" : "1.618" + } + ], + "emitStyle" : "const", + "name" : "Ratio", + "rawType" : "Double", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Ratio", + "tsFullPath" : "Ratio" + }, + { + "cases" : [ + { + "associatedValues" : [ + ], "name" : "north" }, @@ -4579,6 +4651,31 @@ } } }, + { + "abiName" : "bjs_roundTripUInt", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripUInt", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "uint" : { + + } + } + } + ], + "returnType" : { + "uint" : { + + } + } + }, { "abiName" : "bjs_roundTripFloat", "effects" : { @@ -4704,6 +4801,155 @@ } } }, + { + "abiName" : "bjs_roundTripUnsafeRawPointer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripUnsafeRawPointer", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeRawPointer" + } + } + } + } + ], + "returnType" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeRawPointer" + } + } + } + }, + { + "abiName" : "bjs_roundTripUnsafeMutableRawPointer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripUnsafeMutableRawPointer", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutableRawPointer" + } + } + } + } + ], + "returnType" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutableRawPointer" + } + } + } + }, + { + "abiName" : "bjs_roundTripOpaquePointer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOpaquePointer", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "opaquePointer" + } + } + } + } + ], + "returnType" : { + "unsafePointer" : { + "_0" : { + "kind" : "opaquePointer" + } + } + } + }, + { + "abiName" : "bjs_roundTripUnsafePointer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripUnsafePointer", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafePointer", + "pointee" : "UInt8" + } + } + } + } + ], + "returnType" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafePointer", + "pointee" : "UInt8" + } + } + } + }, + { + "abiName" : "bjs_roundTripUnsafeMutablePointer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripUnsafeMutablePointer", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutablePointer", + "pointee" : "UInt8" + } + } + } + } + ], + "returnType" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutablePointer", + "pointee" : "UInt8" + } + } + } + }, { "abiName" : "bjs_roundTripJSObject", "effects" : { @@ -7536,44 +7782,43 @@ } }, { - "abiName" : "bjs_formatName", + "abiName" : "bjs_arrayWithDefault", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "formatName", + "name" : "arrayWithDefault", "parameters" : [ { - "label" : "_", - "name" : "name", - "type" : { - "string" : { - + "defaultValue" : { + "array" : { + "_0" : [ + { + "int" : { + "_0" : 1 + } + }, + { + "int" : { + "_0" : 2 + } + }, + { + "int" : { + "_0" : 3 + } + } + ] } - } - }, - { - "label" : "transform", - "name" : "transform", + }, + "label" : "_", + "name" : "values", "type" : { - "closure" : { + "array" : { "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "20BridgeJSRuntimeTestsSS_SS", - "moduleName" : "BridgeJSRuntimeTests", - "parameters" : [ - { - "string" : { - - } - } - ], - "returnType" : { - "string" : { + "int" : { - } } } } @@ -7581,34 +7826,196 @@ } ], "returnType" : { - "string" : { + "int" : { } } }, { - "abiName" : "bjs_makeFormatter", + "abiName" : "bjs_arrayWithOptionalDefault", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeFormatter", + "name" : "arrayWithOptionalDefault", "parameters" : [ { - "label" : "prefix", - "name" : "prefix", + "defaultValue" : { + "null" : { + + } + }, + "label" : "_", + "name" : "values", "type" : { - "string" : { + "optional" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + } + } + } + } } } } ], "returnType" : { - "closure" : { - "_0" : { - "isAsync" : false, + "int" : { + + } + } + }, + { + "abiName" : "bjs_arrayMixedDefaults", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "arrayMixedDefaults", + "parameters" : [ + { + "defaultValue" : { + "string" : { + "_0" : "Sum" + } + }, + "label" : "prefix", + "name" : "prefix", + "type" : { + "string" : { + + } + } + }, + { + "defaultValue" : { + "array" : { + "_0" : [ + { + "int" : { + "_0" : 10 + } + }, + { + "int" : { + "_0" : 20 + } + } + ] + } + }, + "label" : "values", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "defaultValue" : { + "string" : { + "_0" : "!" + } + }, + "label" : "suffix", + "name" : "suffix", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_formatName", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "formatName", + "parameters" : [ + { + "label" : "_", + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "label" : "transform", + "name" : "transform", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSS_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + } + } + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_makeFormatter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeFormatter", + "parameters" : [ + { + "label" : "prefix", + "name" : "prefix", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, "isThrows" : false, "mangleName" : "20BridgeJSRuntimeTestsSS_SS", "moduleName" : "BridgeJSRuntimeTests", @@ -7629,44 +8036,1191 @@ } }, { - "abiName" : "bjs_makeAdder", + "abiName" : "bjs_makeAdder", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeAdder", + "parameters" : [ + { + "label" : "base", + "name" : "base", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSi_Si", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "int" : { + + } + } + ], + "returnType" : { + "int" : { + + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripIntArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripStringArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripStringArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripDoubleArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripDoubleArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripBoolArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripBoolArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "bool" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "bool" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripDirectionArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripDirectionArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripStatusArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripStatusArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "caseEnum" : { + "_0" : "Status" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "caseEnum" : { + "_0" : "Status" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripThemeArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripThemeArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripHttpStatusArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripHttpStatusArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripDataPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripDataPointArray", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripGreeterArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripGreeterArray", + "parameters" : [ + { + "label" : "_", + "name" : "greeters", + "type" : { + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalIntArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalStringArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalStringArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalDataPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalDataPointArray", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalDirectionArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalDirectionArray", + "parameters" : [ + { + "label" : "_", + "name" : "directions", + "type" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalStatusArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalStatusArray", + "parameters" : [ + { + "label" : "_", + "name" : "statuses", + "type" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "Status" + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "Status" + } + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalIntArrayType", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalIntArrayType", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "optional" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalStringArrayType", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalStringArrayType", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "optional" : { + "_0" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalGreeterArrayType", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalGreeterArrayType", + "parameters" : [ + { + "label" : "_", + "name" : "greeters", + "type" : { + "optional" : { + "_0" : { + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripNestedIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripNestedIntArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripNestedStringArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripNestedStringArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripNestedDoubleArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripNestedDoubleArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripNestedBoolArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripNestedBoolArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "bool" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "bool" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripNestedDataPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripNestedDataPointArray", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripNestedDirectionArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripNestedDirectionArray", + "parameters" : [ + { + "label" : "_", + "name" : "directions", + "type" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripNestedGreeterArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripNestedGreeterArray", + "parameters" : [ + { + "label" : "_", + "name" : "greeters", + "type" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripUnsafeRawPointerArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripUnsafeRawPointerArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeRawPointer" + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeRawPointer" + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripUnsafeMutableRawPointerArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripUnsafeMutableRawPointerArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutableRawPointer" + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutableRawPointer" + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOpaquePointerArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOpaquePointerArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "unsafePointer" : { + "_0" : { + "kind" : "opaquePointer" + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "unsafePointer" : { + "_0" : { + "kind" : "opaquePointer" + } + } + } + } + } + }, + { + "abiName" : "bjs_consumeDataProcessorArrayType", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "consumeDataProcessorArrayType", + "parameters" : [ + { + "label" : "_", + "name" : "processors", + "type" : { + "array" : { + "_0" : { + "swiftProtocol" : { + "_0" : "DataProcessor" + } + } + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_roundTripDataProcessorArrayType", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripDataProcessorArrayType", + "parameters" : [ + { + "label" : "_", + "name" : "processors", + "type" : { + "array" : { + "_0" : { + "swiftProtocol" : { + "_0" : "DataProcessor" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "swiftProtocol" : { + "_0" : "DataProcessor" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripPointerFields", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeAdder", + "name" : "roundTripPointerFields", "parameters" : [ { - "label" : "base", - "name" : "base", + "label" : "_", + "name" : "value", "type" : { - "int" : { - + "swiftStruct" : { + "_0" : "PointerFields" } } } ], "returnType" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "20BridgeJSRuntimeTestsSi_Si", - "moduleName" : "BridgeJSRuntimeTests", - "parameters" : [ - { - "int" : { - - } - } - ], - "returnType" : { - "int" : { - - } - } - } + "swiftStruct" : { + "_0" : "PointerFields" } } }, @@ -7742,6 +9296,56 @@ } } }, + { + "abiName" : "bjs_cartToJSObject", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "cartToJSObject", + "parameters" : [ + { + "label" : "_", + "name" : "cart", + "type" : { + "swiftStruct" : { + "_0" : "CopyableCart" + } + } + } + ], + "returnType" : { + "jsObject" : { + + } + } + }, + { + "abiName" : "bjs_nestedCartToJSObject", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "nestedCartToJSObject", + "parameters" : [ + { + "label" : "_", + "name" : "cart", + "type" : { + "swiftStruct" : { + "_0" : "CopyableNestedCart" + } + } + } + ], + "returnType" : { + "jsObject" : { + + } + } + }, { "abiName" : "bjs_roundTripDataPoint", "effects" : { @@ -7867,6 +9471,56 @@ } } }, + { + "abiName" : "bjs_roundTripAdvancedConfig", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripAdvancedConfig", + "parameters" : [ + { + "label" : "_", + "name" : "config", + "type" : { + "swiftStruct" : { + "_0" : "AdvancedConfig" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "AdvancedConfig" + } + } + }, + { + "abiName" : "bjs_roundTripMeasurementConfig", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripMeasurementConfig", + "parameters" : [ + { + "label" : "_", + "name" : "config", + "type" : { + "swiftStruct" : { + "_0" : "MeasurementConfig" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "MeasurementConfig" + } + } + }, { "abiName" : "bjs_updateValidationReport", "effects" : { @@ -8250,69 +9904,236 @@ "isReadonly" : false, "name" : "optionalTheme", "type" : { - "optional" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + } + }, + { + "isReadonly" : false, + "name" : "httpStatus", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + } + } + }, + { + "isReadonly" : false, + "name" : "apiResult", + "type" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + } + }, + { + "isReadonly" : false, + "name" : "helper", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "isReadonly" : false, + "name" : "optionalHelper", + "type" : { + "optional" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + } + } + ] + } + ], + "structs" : [ + { + "methods" : [ + + ], + "name" : "Point", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "x", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "y", + "type" : { + "int" : { + + } + } + } + ], + "swiftCallName" : "Point" + }, + { + "constructor" : { + "abiName" : "bjs_PointerFields_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "raw", + "name" : "raw", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeRawPointer" + } + } + } + }, + { + "label" : "mutRaw", + "name" : "mutRaw", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutableRawPointer" + } + } + } + }, + { + "label" : "opaque", + "name" : "opaque", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "opaquePointer" + } + } + } + }, + { + "label" : "ptr", + "name" : "ptr", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafePointer", + "pointee" : "UInt8" + } + } + } + }, + { + "label" : "mutPtr", + "name" : "mutPtr", + "type" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutablePointer", + "pointee" : "UInt8" + } + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "PointerFields", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "raw", + "type" : { + "unsafePointer" : { "_0" : { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" - } + "kind" : "unsafeRawPointer" } } } }, { - "isReadonly" : false, - "name" : "httpStatus", + "isReadonly" : true, + "isStatic" : false, + "name" : "mutRaw", "type" : { - "optional" : { + "unsafePointer" : { "_0" : { - "rawValueEnum" : { - "_0" : "HttpStatus", - "_1" : "Int" - } + "kind" : "unsafeMutableRawPointer" } } } }, { - "isReadonly" : false, - "name" : "apiResult", + "isReadonly" : true, + "isStatic" : false, + "name" : "opaque", "type" : { - "optional" : { + "unsafePointer" : { "_0" : { - "associatedValueEnum" : { - "_0" : "APIResult" - } + "kind" : "opaquePointer" } } } }, { - "isReadonly" : false, - "name" : "helper", + "isReadonly" : true, + "isStatic" : false, + "name" : "ptr", "type" : { - "swiftHeapObject" : { - "_0" : "Greeter" + "unsafePointer" : { + "_0" : { + "kind" : "unsafePointer", + "pointee" : "UInt8" + } } } }, { - "isReadonly" : false, - "name" : "optionalHelper", + "isReadonly" : true, + "isStatic" : false, + "name" : "mutPtr", "type" : { - "optional" : { + "unsafePointer" : { "_0" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } + "kind" : "unsafeMutablePointer", + "pointee" : "UInt8" } } } } - ] - } - ], - "structs" : [ + ], + "swiftCallName" : "PointerFields" + }, { "constructor" : { "abiName" : "bjs_DataPoint_init", @@ -8454,58 +10275,263 @@ "isStatic" : false, "name" : "street", "type" : { - "string" : { - + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "city", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "zipCode", + "type" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "swiftCallName" : "Address" + }, + { + "methods" : [ + + ], + "name" : "Contact", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "age", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "address", + "type" : { + "swiftStruct" : { + "_0" : "Address" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "email", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "secondaryAddress", + "type" : { + "optional" : { + "_0" : { + "swiftStruct" : { + "_0" : "Address" + } + } + } + } + } + ], + "swiftCallName" : "Contact" + }, + { + "methods" : [ + + ], + "name" : "Config", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "theme", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "direction", + "type" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "status", + "type" : { + "caseEnum" : { + "_0" : "Status" + } + } + } + ], + "swiftCallName" : "Config" + }, + { + "methods" : [ + + ], + "name" : "SessionData", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "id", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "owner", + "type" : { + "optional" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + } + } + ], + "swiftCallName" : "SessionData" + }, + { + "methods" : [ + + ], + "name" : "ValidationReport", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "id", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "APIResult" } } }, { "isReadonly" : true, "isStatic" : false, - "name" : "city", + "name" : "status", "type" : { - "string" : { - + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "Status" + } + } } } }, { "isReadonly" : true, "isStatic" : false, - "name" : "zipCode", + "name" : "outcome", "type" : { "optional" : { "_0" : { - "int" : { - + "associatedValueEnum" : { + "_0" : "APIResult" } } } } } ], - "swiftCallName" : "Address" + "swiftCallName" : "ValidationReport" }, { "methods" : [ ], - "name" : "Contact", + "name" : "AdvancedConfig", "properties" : [ { "isReadonly" : true, "isStatic" : false, - "name" : "name", - "type" : { - "string" : { - - } - } - }, - { - "isReadonly" : true, - "isStatic" : false, - "name" : "age", + "name" : "id", "type" : { "int" : { @@ -8515,70 +10541,53 @@ { "isReadonly" : true, "isStatic" : false, - "name" : "address", + "name" : "title", "type" : { - "swiftStruct" : { - "_0" : "Address" + "string" : { + } } }, { "isReadonly" : true, "isStatic" : false, - "name" : "email", + "name" : "enabled", "type" : { - "optional" : { - "_0" : { - "string" : { + "bool" : { - } - } } } }, { "isReadonly" : true, "isStatic" : false, - "name" : "secondaryAddress", + "name" : "theme", "type" : { - "optional" : { - "_0" : { - "swiftStruct" : { - "_0" : "Address" - } - } + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" } } - } - ], - "swiftCallName" : "Contact" - }, - { - "methods" : [ - - ], - "name" : "Config", - "properties" : [ + }, { "isReadonly" : true, "isStatic" : false, - "name" : "name", + "name" : "status", "type" : { - "string" : { - + "caseEnum" : { + "_0" : "Status" } } }, { "isReadonly" : true, "isStatic" : false, - "name" : "theme", + "name" : "result", "type" : { "optional" : { "_0" : { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" + "associatedValueEnum" : { + "_0" : "APIResult" } } } @@ -8587,12 +10596,12 @@ { "isReadonly" : true, "isStatic" : false, - "name" : "direction", + "name" : "metadata", "type" : { "optional" : { "_0" : { - "caseEnum" : { - "_0" : "Direction" + "jsObject" : { + } } } @@ -8601,84 +10610,82 @@ { "isReadonly" : true, "isStatic" : false, - "name" : "status", + "name" : "location", "type" : { - "caseEnum" : { - "_0" : "Status" + "optional" : { + "_0" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + } } } - } - ], - "swiftCallName" : "Config" - }, - { - "methods" : [ - - ], - "name" : "SessionData", - "properties" : [ + }, { "isReadonly" : true, "isStatic" : false, - "name" : "id", + "name" : "defaults", "type" : { - "int" : { - + "swiftStruct" : { + "_0" : "ConfigStruct" } } }, { "isReadonly" : true, "isStatic" : false, - "name" : "owner", + "name" : "overrideDefaults", "type" : { "optional" : { "_0" : { - "swiftHeapObject" : { - "_0" : "Greeter" + "swiftStruct" : { + "_0" : "ConfigStruct" } } } } } ], - "swiftCallName" : "SessionData" + "swiftCallName" : "AdvancedConfig" }, { "methods" : [ ], - "name" : "ValidationReport", + "name" : "MeasurementConfig", "properties" : [ { "isReadonly" : true, "isStatic" : false, - "name" : "id", + "name" : "precision", "type" : { - "int" : { - + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" } } }, { "isReadonly" : true, "isStatic" : false, - "name" : "result", + "name" : "ratio", "type" : { - "associatedValueEnum" : { - "_0" : "APIResult" + "rawValueEnum" : { + "_0" : "Ratio", + "_1" : "Double" } } }, { "isReadonly" : true, "isStatic" : false, - "name" : "status", + "name" : "optionalPrecision", "type" : { "optional" : { "_0" : { - "caseEnum" : { - "_0" : "Status" + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" } } } @@ -8687,19 +10694,20 @@ { "isReadonly" : true, "isStatic" : false, - "name" : "outcome", + "name" : "optionalRatio", "type" : { "optional" : { "_0" : { - "associatedValueEnum" : { - "_0" : "APIResult" + "rawValueEnum" : { + "_0" : "Ratio", + "_1" : "Double" } } } } } ], - "swiftCallName" : "ValidationReport" + "swiftCallName" : "MeasurementConfig" }, { "constructor" : { @@ -8819,41 +10827,204 @@ } }, { - "label" : "b", - "name" : "b", + "label" : "b", + "name" : "b", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "double" : { + + } + }, + "staticContext" : { + "structName" : { + "_0" : "MathOperations" + } + } + } + ], + "name" : "MathOperations", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "baseValue", + "type" : { + "double" : { + + } + } + } + ], + "swiftCallName" : "MathOperations" + }, + { + "methods" : [ + { + "abiName" : "bjs_CopyableCart_static_fromJSObject", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "fromJSObject", + "parameters" : [ + { + "label" : "_", + "name" : "object", + "type" : { + "jsObject" : { + + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "CopyableCart" + } + }, + "staticContext" : { + "structName" : { + "_0" : "CopyableCart" + } + } + } + ], + "name" : "CopyableCart", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "x", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "note", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "swiftCallName" : "CopyableCart" + }, + { + "methods" : [ + + ], + "name" : "CopyableCartItem", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "sku", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "quantity", + "type" : { + "int" : { + + } + } + } + ], + "swiftCallName" : "CopyableCartItem" + }, + { + "methods" : [ + { + "abiName" : "bjs_CopyableNestedCart_static_fromJSObject", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "fromJSObject", + "parameters" : [ + { + "label" : "_", + "name" : "object", "type" : { - "double" : { + "jsObject" : { } } } ], "returnType" : { - "double" : { - + "swiftStruct" : { + "_0" : "CopyableNestedCart" } }, "staticContext" : { "structName" : { - "_0" : "MathOperations" + "_0" : "CopyableNestedCart" } } } ], - "name" : "MathOperations", + "name" : "CopyableNestedCart", "properties" : [ { "isReadonly" : true, "isStatic" : false, - "name" : "baseValue", + "name" : "id", "type" : { - "double" : { + "int" : { } } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "item", + "type" : { + "swiftStruct" : { + "_0" : "CopyableCartItem" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "shippingAddress", + "type" : { + "optional" : { + "_0" : { + "swiftStruct" : { + "_0" : "Address" + } + } + } + } } ], - "swiftCallName" : "MathOperations" + "swiftCallName" : "CopyableNestedCart" }, { "methods" : [ @@ -9155,6 +11326,48 @@ "_0" : "JSPromise" } } + }, + { + "jsName" : "$jsWeirdFunction", + "name" : "_jsWeirdFunction", + "parameters" : [ + + ], + "returnType" : { + "double" : { + + } + } + }, + { + "from" : "global", + "name" : "parseInt", + "parameters" : [ + { + "name" : "string", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "double" : { + + } + } + } + ], + "globalGetters" : [ + { + "from" : "global", + "name" : "globalObject1", + "type" : { + "jsObject" : { + + } + } } ], "types" : [ @@ -9236,6 +11449,146 @@ "type" : { "string" : { + } + } + } + ] + }, + { + "constructor" : { + "parameters" : [ + + ] + }, + "getters" : [ + + ], + "jsName" : "$WeirdClass", + "methods" : [ + { + "jsName" : "method-with-dashes", + "name" : "method_with_dashes", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "_WeirdClass", + "setters" : [ + + ] + }, + { + "constructor" : { + "parameters" : [ + { + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "name" : "age", + "type" : { + "double" : { + + } + } + }, + { + "name" : "isCat", + "type" : { + "bool" : { + + } + } + } + ] + }, + "from" : "global", + "getters" : [ + { + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "name" : "age", + "type" : { + "double" : { + + } + } + }, + { + "name" : "isCat", + "type" : { + "bool" : { + + } + } + } + ], + "methods" : [ + { + "name" : "bark", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "name" : "getIsCat", + "parameters" : [ + + ], + "returnType" : { + "bool" : { + + } + } + } + ], + "name" : "Animal", + "setters" : [ + { + "functionName" : "name_set", + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "functionName" : "age_set", + "name" : "age", + "type" : { + "double" : { + + } + } + }, + { + "functionName" : "isCat_set", + "name" : "isCat", + "type" : { + "bool" : { + } } } @@ -9251,6 +11604,14 @@ ] }, + { + "functions" : [ + + ], + "types" : [ + + ] + }, { "functions" : [ { @@ -9455,6 +11816,63 @@ ], "types" : [ + ] + }, + { + "functions" : [ + { + "name" : "jsTranslatePoint", + "parameters" : [ + { + "name" : "point", + "type" : { + "swiftStruct" : { + "_0" : "Point" + } + } + }, + { + "name" : "dx", + "type" : { + "int" : { + + } + } + }, + { + "name" : "dy", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + ], + "types" : [ + + ] + }, + { + "functions" : [ + + ], + "types" : [ + + ] + }, + { + "functions" : [ + + ], + "types" : [ + ] } ] diff --git a/Tests/BridgeJSRuntimeTests/GlobalThisImportTests.swift b/Tests/BridgeJSRuntimeTests/GlobalThisImportTests.swift new file mode 100644 index 000000000..2f6251341 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/GlobalThisImportTests.swift @@ -0,0 +1,19 @@ +import XCTest +import JavaScriptKit + +final class GlobalThisImportTests: XCTestCase { + func testGlobalFunctionImport() throws { + XCTAssertEqual(try parseInt("42"), 42) + } + + func testGlobalClassImport() throws { + let cat = try Animal("Mimi", 3, true) + XCTAssertEqual(try cat.bark(), "nyan") + XCTAssertEqual(try cat.getIsCat(), true) + } + + func testGlobalGetterImport() throws { + let value = try globalObject1["prop_2"].number + XCTAssertEqual(value, 2) + } +} diff --git a/Tests/BridgeJSRuntimeTests/ImportAPITests.swift b/Tests/BridgeJSRuntimeTests/ImportAPITests.swift index 5ceca3bf0..ea9f8c68f 100644 --- a/Tests/BridgeJSRuntimeTests/ImportAPITests.swift +++ b/Tests/BridgeJSRuntimeTests/ImportAPITests.swift @@ -120,4 +120,11 @@ class ImportAPITests: XCTestCase { XCTAssertEqual(ret, 5) XCTAssertEqual(total, 10) } + + func testJSNameFunctionAndClass() throws { + XCTAssertEqual(try _jsWeirdFunction(), 42) + + let obj = try _WeirdClass() + XCTAssertEqual(try obj.method_with_dashes(), "ok") + } } diff --git a/Tests/BridgeJSRuntimeTests/ImportStructAPIs.swift b/Tests/BridgeJSRuntimeTests/ImportStructAPIs.swift new file mode 100644 index 000000000..82908701c --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/ImportStructAPIs.swift @@ -0,0 +1,9 @@ +@_spi(Experimental) import JavaScriptKit + +@JS +struct Point { + var x: Int + var y: Int +} + +@JSFunction func jsTranslatePoint(_ point: Point, dx: Int, dy: Int) throws(JSException) -> Point diff --git a/Tests/BridgeJSRuntimeTests/StructAPIs.swift b/Tests/BridgeJSRuntimeTests/StructAPIs.swift new file mode 100644 index 000000000..5c9fed511 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/StructAPIs.swift @@ -0,0 +1,216 @@ +@_spi(Experimental) import JavaScriptKit + +@JS struct PointerFields { + var raw: UnsafeRawPointer + var mutRaw: UnsafeMutableRawPointer + var opaque: OpaquePointer + var ptr: UnsafePointer + var mutPtr: UnsafeMutablePointer + + @JS init( + raw: UnsafeRawPointer, + mutRaw: UnsafeMutableRawPointer, + opaque: OpaquePointer, + ptr: UnsafePointer, + mutPtr: UnsafeMutablePointer + ) { + self.raw = raw + self.mutRaw = mutRaw + self.opaque = opaque + self.ptr = ptr + self.mutPtr = mutPtr + } +} + +@JS func roundTripPointerFields(_ value: PointerFields) -> PointerFields { value } + +@JS struct DataPoint { + let x: Double + let y: Double + var label: String + var optCount: Int? + var optFlag: Bool? + + @JS init(x: Double, y: Double, label: String, optCount: Int?, optFlag: Bool?) { + self.x = x + self.y = y + self.label = label + self.optCount = optCount + self.optFlag = optFlag + } +} + +@JS struct Address { + var street: String + var city: String + var zipCode: Int? +} + +@JS struct Contact { + var name: String + var age: Int + var address: Address + var email: String? + var secondaryAddress: Address? +} + +@JS struct Config { + var name: String + var theme: Theme? + var direction: Direction? + var status: Status +} + +@JS struct SessionData { + var id: Int + var owner: Greeter? +} + +@JS struct ValidationReport { + var id: Int + var result: APIResult + var status: Status? + var outcome: APIResult? +} + +@JS struct AdvancedConfig { + var id: Int + var title: String + var enabled: Bool + var theme: Theme + var status: Status + var result: APIResult? + var metadata: JSObject? + var location: DataPoint? + var defaults: ConfigStruct + var overrideDefaults: ConfigStruct? +} + +@JS struct MeasurementConfig { + var precision: Precision + var ratio: Ratio + var optionalPrecision: Precision? + var optionalRatio: Ratio? +} + +@JS struct MathOperations { + var baseValue: Double + + @JS init(baseValue: Double = 0.0) { + self.baseValue = baseValue + } + + @JS func add(a: Double, b: Double = 10.0) -> Double { + return baseValue + a + b + } + + @JS func multiply(a: Double, b: Double) -> Double { + return a * b + } + + @JS static func subtract(a: Double, b: Double) -> Double { + return a - b + } +} + +@JS func testStructDefault( + point: DataPoint = DataPoint(x: 1.0, y: 2.0, label: "default", optCount: nil, optFlag: nil) +) -> String { + return "\(point.x),\(point.y),\(point.label)" +} + +@JS struct CopyableCart { + var x: Int + var note: String? + + @JS static func fromJSObject(_ object: JSObject) -> CopyableCart { + CopyableCart(unsafelyCopying: object) + } +} + +@JS func cartToJSObject(_ cart: CopyableCart) -> JSObject { + cart.toJSObject() +} + +@JS struct CopyableCartItem { + var sku: String + var quantity: Int +} + +@JS struct CopyableNestedCart { + var id: Int + var item: CopyableCartItem + var shippingAddress: Address? + + @JS static func fromJSObject(_ object: JSObject) -> CopyableNestedCart { + CopyableNestedCart(unsafelyCopying: object) + } +} + +@JS func nestedCartToJSObject(_ cart: CopyableNestedCart) -> JSObject { + cart.toJSObject() +} + +@JS struct ConfigStruct { + var name: String + var value: Int + + @JS nonisolated(unsafe) static var defaultConfig: String = "production" + @JS static let maxRetries: Int = 3 + @JS nonisolated(unsafe) static var timeout: Double = 30.0 + + @JS static var computedSetting: String { + return "Config: \(defaultConfig)" + } +} + +@JS func roundTripDataPoint(_ data: DataPoint) -> DataPoint { + return data +} + +@JS func roundTripContact(_ contact: Contact) -> Contact { + return contact +} + +@JS func roundTripConfig(_ config: Config) -> Config { + return config +} + +@JS func roundTripSessionData(_ session: SessionData) -> SessionData { + return session +} + +@JS func roundTripValidationReport(_ report: ValidationReport) -> ValidationReport { + return report +} + +@JS func roundTripAdvancedConfig(_ config: AdvancedConfig) -> AdvancedConfig { + return config +} + +@JS func roundTripMeasurementConfig(_ config: MeasurementConfig) -> MeasurementConfig { + return config +} + +@JS func updateValidationReport(_ newResult: APIResult?, _ report: ValidationReport) -> ValidationReport { + return ValidationReport( + id: report.id, + result: newResult ?? report.result, + status: report.status, + outcome: report.outcome + ) +} + +@JS class Container { + @JS var location: DataPoint + @JS var config: Config? + + @JS init(location: DataPoint, config: Config?) { + self.location = location + self.config = config + } +} + +@JS func testContainerWithStruct(_ point: DataPoint) -> Container { + return Container(location: point, config: nil) +} diff --git a/Tests/BridgeJSRuntimeTests/SwiftStructTests.swift b/Tests/BridgeJSRuntimeTests/SwiftStructTests.swift new file mode 100644 index 000000000..3ba9d28d6 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/SwiftStructTests.swift @@ -0,0 +1,19 @@ +import XCTest +import JavaScriptKit + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "runJsStructWorks") +@_extern(c) +func runJsStructWorks() -> Void + +final class SwiftStructTests: XCTestCase { + func testExportedStructSupport() { + runJsStructWorks() + } + + func testSwiftStructInImportedSignature() throws { + let point = Point(x: 1, y: 2) + let moved = try jsTranslatePoint(point, dx: 3, dy: -1) + XCTAssertEqual(moved.x, 4) + XCTAssertEqual(moved.y, 1) + } +} diff --git a/Tests/BridgeJSRuntimeTests/bridge-js.d.ts b/Tests/BridgeJSRuntimeTests/bridge-js.d.ts index 87de440d8..983d6052d 100644 --- a/Tests/BridgeJSRuntimeTests/bridge-js.d.ts +++ b/Tests/BridgeJSRuntimeTests/bridge-js.d.ts @@ -23,3 +23,11 @@ export class JsGreeter { } export function runAsyncWorks(): Promise; + +// jsName tests +export function $jsWeirdFunction(): number; + +export class $WeirdClass { + constructor(); + "method-with-dashes"(): string; +} diff --git a/Tests/BridgeJSRuntimeTests/bridge-js.global.d.ts b/Tests/BridgeJSRuntimeTests/bridge-js.global.d.ts new file mode 100644 index 000000000..b856ce8bd --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/bridge-js.global.d.ts @@ -0,0 +1,15 @@ +// Declarations in this file are imported from `globalThis`. + +export function parseInt(string: string): number; + +export class Animal { + name: string; + age: number; + isCat: boolean; + constructor(name: string, age: number, isCat: boolean); + bark(): string; + getIsCat(): boolean; +} + +export const globalObject1: any; + diff --git a/Tests/JavaScriptKitTests/JSTracingTests.swift b/Tests/JavaScriptKitTests/JSTracingTests.swift new file mode 100644 index 000000000..84fb9bfc6 --- /dev/null +++ b/Tests/JavaScriptKitTests/JSTracingTests.swift @@ -0,0 +1,53 @@ +#if Tracing +import JavaScriptKit +import XCTest + +final class JSTracingTests: XCTestCase { + func testJSCallHookReportsMethod() throws { + var startInfo: [JSTracing.JSCallInfo] = [] + var ended = 0 + let remove = JSTracing.default.addJSCallHook { info in + startInfo.append(info) + return { ended += 1 } + } + defer { remove() } + + let globalObject1 = JSObject.global.globalObject1 + let prop5 = try XCTUnwrap(globalObject1.prop_5.object) + _ = prop5.func6!(true, 1, 2) + + XCTAssertEqual(startInfo.count, 1) + guard case let .method(receiver, methodName, arguments) = startInfo.first else { + XCTFail("Expected method info") + return + } + XCTAssertEqual(receiver.id, prop5.id) + XCTAssertEqual(methodName, "func6") + XCTAssertEqual(arguments, [.boolean(true), .number(1), .number(2)]) + XCTAssertEqual(ended, 1) + } + + func testJSClosureCallHookReportsMetadata() throws { + var startInfo: [JSTracing.JSClosureCallInfo] = [] + var ended = 0 + let remove = JSTracing.default.addJSClosureCallHook { info in + startInfo.append(info) + return { ended += 1 } + } + defer { remove() } + + let globalObject1 = JSObject.global.globalObject1 + let prop6 = try XCTUnwrap(globalObject1.prop_6.object) + let closure = JSClosure(file: "TracingTests.swift", line: 4242) { _ in .number(7) } + prop6.host_func_1 = .object(closure) + + let callHost = try XCTUnwrap(prop6.call_host_1.function) + XCTAssertEqual(callHost(), .number(7)) + + XCTAssertEqual(startInfo.count, 1) + XCTAssertEqual(startInfo.first?.fileID, "TracingTests.swift") + XCTAssertEqual(startInfo.first?.line, 4242) + XCTAssertEqual(ended, 1) + } +} +#endif diff --git a/Tests/JavaScriptKitTests/JavaScriptKitTests.swift b/Tests/JavaScriptKitTests/JavaScriptKitTests.swift index 0a6fc9ce2..b69334ce5 100644 --- a/Tests/JavaScriptKitTests/JavaScriptKitTests.swift +++ b/Tests/JavaScriptKitTests/JavaScriptKitTests.swift @@ -21,8 +21,8 @@ class JavaScriptKitTests: XCTestCase { let prop = JSString("prop_\(index)") setJSValue(this: global, name: prop, value: input) let got = getJSValue(this: global, name: prop) - switch (got, input) { - case (.number(let lhs), .number(let rhs)): + switch (got.number, input.number) { + case (let lhs?, let rhs?): // Compare bitPattern because nan == nan is always false XCTAssertEqual(lhs.bitPattern, rhs.bitPattern) default: diff --git a/Tests/prelude.mjs b/Tests/prelude.mjs index 66283b723..12307d605 100644 --- a/Tests/prelude.mjs +++ b/Tests/prelude.mjs @@ -8,6 +8,7 @@ import { export async function setupOptions(options, context) { Error.stackTraceLimit = 100; setupTestGlobals(globalThis); + return { ...options, getImports: (importsContext) => { @@ -50,6 +51,9 @@ export async function setupOptions(options, context) { "jsRoundTripFeatureFlag": (flag) => { return flag; }, + "$jsWeirdFunction": () => { + return 42; + }, JsGreeter: class { /** * @param {string} name @@ -67,6 +71,13 @@ export async function setupOptions(options, context) { this.name = name; } }, + $WeirdClass: class { + constructor() { + } + ["method-with-dashes"]() { + return "ok"; + } + }, Foo: ImportedFoo, runAsyncWorks: async () => { const exports = importsContext.getExports(); @@ -92,6 +103,9 @@ export async function setupOptions(options, context) { fn(v); fn(v); return v; + }, + jsTranslatePoint: (point, dx, dy) => { + return { x: (point.x | 0) + (dx | 0), y: (point.y | 0) + (dy | 0) }; } }; }, @@ -109,6 +123,13 @@ export async function setupOptions(options, context) { } return BridgeJSRuntimeTests_runJsWorks(getInstance(), exports); } + bridgeJSRuntimeTests["runJsStructWorks"] = () => { + const exports = getExports(); + if (!exports) { + throw new Error("No exports!?"); + } + return BridgeJSRuntimeTests_runJsStructWorks(exports); + } const bridgeJSGlobalTests = importObject["BridgeJSGlobalTests"] || {}; bridgeJSGlobalTests["runJsWorksGlobal"] = () => { return BridgeJSGlobalTests_runJsWorksGlobal(); @@ -134,6 +155,9 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { for (const v of [0, 1, -1, 2147483647, -2147483648]) { assert.equal(exports.roundTripInt(v), v); } + for (const v of [0, 1, 2147483647, 4294967295]) { + assert.equal(exports.roundTripUInt(v), v); + } for (const v of [ 0.0, 1.0, -1.0, NaN, @@ -166,6 +190,14 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { assert.equal(exports.roundTripString(v), v); } + for (const p of [1, 4, 1024, 65536, 2147483647]) { + assert.equal(exports.roundTripUnsafeRawPointer(p), p); + assert.equal(exports.roundTripUnsafeMutableRawPointer(p), p); + assert.equal(exports.roundTripOpaquePointer(p), p); + assert.equal(exports.roundTripUnsafePointer(p), p); + assert.equal(exports.roundTripUnsafeMutablePointer(p), p); + } + const g = new exports.Greeter("John"); assert.equal(g.greet(), "Hello, John!"); @@ -440,6 +472,13 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { assert.equal(HttpStatusValues.ServerError, 500); assert.equal(HttpStatusValues.Unknown, -1); + assert.equal(exports.Precision.Rough, 0.1); + assert.equal(exports.Precision.Normal, 0.01); + assert.equal(exports.Precision.Fine, 0.001); + assert.equal(exports.Ratio.Quarter, 0.25); + assert.equal(exports.Ratio.Half, 0.5); + assert.equal(exports.Ratio.Golden, 1.618); + assert.equal(exports.setTheme(exports.Theme.Light), exports.Theme.Light); assert.equal(exports.setTheme(exports.Theme.Dark), exports.Theme.Dark); assert.equal(exports.getTheme(), ThemeValues.Light); @@ -742,7 +781,7 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { testProtocolSupport(exports); testClosureSupport(exports); - testStructSupport(exports); + testArraySupport(exports); } /** @param {import('./../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */ function testClosureSupport(exports) { @@ -945,6 +984,9 @@ function testStructSupport(exports) { const data2 = { x: 0.0, y: 0.0, label: "", optCount: null, optFlag: null }; assert.deepEqual(exports.roundTripDataPoint(data2), data2); + const pointerFields1 = { raw: 1, mutRaw: 4, opaque: 1024, ptr: 65536, mutPtr: 2 }; + assert.deepEqual(exports.roundTripPointerFields(pointerFields1), pointerFields1); + const contact1 = { name: "Alice", age: 30, @@ -1015,6 +1057,34 @@ function testStructSupport(exports) { assert.deepEqual(updatedReport.result, { tag: exports.APIResult.Tag.Success, param0: "updated" }); assert.deepEqual(exports.updateValidationReport(null, origReport).result, origReport.result); + const advancedConfig1 = { + id: 42, + title: "Primary", + enabled: true, + theme: exports.Theme.Dark, + status: exports.Status.Success, + result: { tag: exports.APIResult.Tag.Success, param0: "ok" }, + metadata: { note: "extra" }, + location: data1, + defaults: { name: "base", value: 10 }, + overrideDefaults: { name: "override", value: 20 }, + }; + assert.deepEqual(exports.roundTripAdvancedConfig(advancedConfig1), advancedConfig1); + + const advancedConfig2 = { + id: 99, + title: "", + enabled: false, + theme: exports.Theme.Light, + status: exports.Status.Loading, + result: null, + metadata: null, + location: null, + defaults: { name: "base", value: 0 }, + overrideDefaults: null, + }; + assert.deepEqual(exports.roundTripAdvancedConfig(advancedConfig2), advancedConfig2); + assert.equal(exports.MathOperations.subtract(10.0, 4.0), 6.0); const mathOps = exports.MathOperations.init(); assert.equal(mathOps.baseValue, 0.0); @@ -1032,6 +1102,31 @@ function testStructSupport(exports) { const customPoint = { x: 10.0, y: 20.0, label: "custom", optCount: null, optFlag: null }; assert.equal(exports.testStructDefault(customPoint), "10.0,20.0,custom"); + // Test @JS struct init(unsafelyCopying:) + toJSObject() + const cart1 = { x: 123, note: "hello" }; + assert.deepEqual(exports.CopyableCart.fromJSObject(cart1), cart1); + assert.deepEqual(exports.cartToJSObject(cart1), cart1); + + const cart2 = { x: 1 }; + assert.deepEqual(exports.CopyableCart.fromJSObject(cart2), { x: 1, note: null }); + assert.deepEqual(exports.cartToJSObject(cart2), { x: 1, note: null }); + + const nestedCart1 = { + id: 7, + item: { sku: "ABC-123", quantity: 2 }, + shippingAddress: { street: "1 Swift Way", city: "WasmCity", zipCode: 12345 }, + }; + assert.deepEqual(exports.CopyableNestedCart.fromJSObject(nestedCart1), nestedCart1); + assert.deepEqual(exports.nestedCartToJSObject(nestedCart1), nestedCart1); + + const nestedCart2 = { + id: 8, + item: { sku: "XYZ-999", quantity: 0 }, + shippingAddress: null, + }; + assert.deepEqual(exports.CopyableNestedCart.fromJSObject(nestedCart2), nestedCart2); + assert.deepEqual(exports.nestedCartToJSObject(nestedCart2), nestedCart2); + const container = exports.testContainerWithStruct({ x: 5.0, y: 10.0, label: "test", optCount: null, optFlag: true }); assert.equal(container.location.x, 5.0); assert.equal(container.config, null); @@ -1043,6 +1138,22 @@ function testStructSupport(exports) { exports.ConfigStruct.defaultConfig = "staging"; assert.equal(exports.ConfigStruct.computedSetting, "Config: staging"); exports.ConfigStruct.defaultConfig = "production"; + + const { Precision, Ratio } = exports; + const mc1 = { + precision: Math.fround(Precision.Rough), + ratio: Ratio.Golden, + optionalPrecision: Math.fround(Precision.Fine), + optionalRatio: Ratio.Half + }; + assert.deepEqual(exports.roundTripMeasurementConfig(mc1), mc1); + const mc2 = { + precision: Math.fround(Precision.Normal), + ratio: Ratio.Quarter, + optionalPrecision: null, + optionalRatio: null + }; + assert.deepEqual(exports.roundTripMeasurementConfig(mc2), mc2); } /** @param {import('./../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */ @@ -1050,6 +1161,11 @@ async function BridgeJSRuntimeTests_runAsyncWorks(exports) { await exports.asyncRoundTripVoid(); } +/** @param {import('./../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */ +function BridgeJSRuntimeTests_runJsStructWorks(exports) { + testStructSupport(exports); +} + function BridgeJSGlobalTests_runJsWorksGlobal() { assert.equal(globalThis.GlobalNetworking.API.CallMethodValues.Get, 0); assert.equal(globalThis.GlobalNetworking.API.CallMethodValues.Post, 1); @@ -1188,6 +1304,129 @@ function setupTestGlobals(global) { }; } +/** @param {import('./../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */ +function testArraySupport(exports) { + const { Direction, Status, Theme, HttpStatus, Greeter } = exports; + + // Primitive arrays + assert.deepEqual(exports.roundTripIntArray([1, 2, 3, -10, 2147483647]), [1, 2, 3, -10, 2147483647]); + assert.deepEqual(exports.roundTripIntArray([]), []); + assert.deepEqual(exports.roundTripStringArray(["Hello", "World", ""]), ["Hello", "World", ""]); + const doubles = exports.roundTripDoubleArray([1.5, 0.0, -1.5, Infinity, NaN]); + assert.equal(doubles[0], 1.5); + assert(Number.isNaN(doubles[4])); + assert.deepEqual(exports.roundTripBoolArray([true, false, true]), [true, false, true]); + + // Enum arrays + assert.deepEqual(exports.roundTripDirectionArray([Direction.North, Direction.South]), [Direction.North, Direction.South]); + assert.deepEqual(exports.roundTripStatusArray([Status.Loading, Status.Success]), [Status.Loading, Status.Success]); + assert.deepEqual(exports.roundTripThemeArray([Theme.Light, Theme.Dark]), [Theme.Light, Theme.Dark]); + assert.deepEqual(exports.roundTripHttpStatusArray([HttpStatus.Ok, HttpStatus.NotFound]), [HttpStatus.Ok, HttpStatus.NotFound]); + + // Struct arrays + const points = [ + { x: 1.0, y: 2.0, label: "A", optCount: 10, optFlag: true }, + { x: 3.0, y: 4.0, label: "B", optCount: null, optFlag: null } + ]; + const pointResult = exports.roundTripDataPointArray(points); + assert.equal(pointResult[0].optCount, 10); + assert.equal(pointResult[1].optCount, null); + + // Class arrays + const g1 = new Greeter("Alice"); + const g2 = new Greeter("Bob"); + const gResult = exports.roundTripGreeterArray([g1, g2]); + assert.equal(gResult[0].name, "Alice"); + assert.equal(gResult[1].greet(), "Hello, Bob!"); + g1.release(); g2.release(); + gResult.forEach(g => g.release()); + + // Arrays of optional elements + assert.deepEqual(exports.roundTripOptionalIntArray([1, null, 3]), [1, null, 3]); + assert.deepEqual(exports.roundTripOptionalStringArray(["a", null, "b"]), ["a", null, "b"]); + const optPoint = { x: 1.0, y: 2.0, label: "", optCount: null, optFlag: null }; + const optPoints = exports.roundTripOptionalDataPointArray([optPoint, null]); + assert.deepEqual(optPoints[0], optPoint); + assert.equal(optPoints[1], null); + assert.deepEqual(exports.roundTripOptionalDirectionArray([Direction.North, null]), [Direction.North, null]); + assert.deepEqual(exports.roundTripOptionalStatusArray([Status.Success, null]), [Status.Success, null]); + + // Optional arrays + assert.deepEqual(exports.roundTripOptionalIntArrayType([1, 2, 3]), [1, 2, 3]); + assert.equal(exports.roundTripOptionalIntArrayType(null), null); + assert.deepEqual(exports.roundTripOptionalStringArrayType(["a", "b"]), ["a", "b"]); + assert.equal(exports.roundTripOptionalStringArrayType(null), null); + const og1 = new Greeter("OptGreeter"); + const optGreeterResult = exports.roundTripOptionalGreeterArrayType([og1]); + assert.equal(optGreeterResult[0].name, "OptGreeter"); + assert.equal(exports.roundTripOptionalGreeterArrayType(null), null); + og1.release(); + optGreeterResult.forEach(g => g.release()); + + // Nested arrays + assert.deepEqual(exports.roundTripNestedIntArray([[1, 2], [3]]), [[1, 2], [3]]); + assert.deepEqual(exports.roundTripNestedIntArray([[1, 2], [], [3]]), [[1, 2], [], [3]]); + assert.deepEqual(exports.roundTripNestedStringArray([["a", "b"], ["c"]]), [["a", "b"], ["c"]]); + assert.deepEqual(exports.roundTripNestedDoubleArray([[1.5], [2.5]]), [[1.5], [2.5]]); + assert.deepEqual(exports.roundTripNestedBoolArray([[true], [false]]), [[true], [false]]); + const nestedPoint = { x: 1.0, y: 2.0, label: "A", optCount: null, optFlag: null }; + assert.deepEqual(exports.roundTripNestedDataPointArray([[nestedPoint]])[0][0], nestedPoint); + assert.deepEqual(exports.roundTripNestedDirectionArray([[Direction.North], [Direction.South]]), [[Direction.North], [Direction.South]]); + const ng1 = new Greeter("Nested1"); + const ng2 = new Greeter("Nested2"); + const nestedGreeters = exports.roundTripNestedGreeterArray([[ng1], [ng2]]); + assert.equal(nestedGreeters[0][0].name, "Nested1"); + assert.equal(nestedGreeters[1][0].greet(), "Hello, Nested2!"); + ng1.release(); ng2.release(); + nestedGreeters.forEach(row => row.forEach(g => g.release())); + + // UnsafePointer-family arrays + const pointerValues = [1, 4, 1024, 65536, 2147483647]; + assert.deepEqual(exports.roundTripUnsafeRawPointerArray(pointerValues), pointerValues); + assert.deepEqual(exports.roundTripUnsafeMutableRawPointerArray(pointerValues), pointerValues); + assert.deepEqual(exports.roundTripOpaquePointerArray(pointerValues), pointerValues); + assert.deepEqual(exports.roundTripUnsafeRawPointerArray([]), []); + + // Default values + assert.equal(exports.arrayWithDefault(), 6); + assert.equal(exports.arrayWithDefault([10, 20]), 30); + assert.equal(exports.arrayWithOptionalDefault(), -1); + assert.equal(exports.arrayWithOptionalDefault(null), -1); + assert.equal(exports.arrayWithOptionalDefault([5, 5]), 10); + assert.equal(exports.arrayMixedDefaults(), "Sum: 30!"); + assert.equal(exports.arrayMixedDefaults("Total"), "Total: 30!"); + assert.equal(exports.arrayMixedDefaults("Total", [1, 2, 3]), "Total: 6!"); + assert.equal(exports.arrayMixedDefaults("Val", [100], "?"), "Val: 100?"); + assert.equal(exports.arrayMixedDefaults(undefined, [5, 5]), "Sum: 10!"); + assert.equal(exports.arrayMixedDefaults(undefined, undefined, "?"), "Sum: 30?"); + + const helper1 = new exports.Greeter("Helper1"); + const jsProcessor1 = { + count: 1, name: "Processor1", optionalTag: null, optionalCount: null, + direction: null, optionalTheme: null, httpStatus: null, apiResult: null, + helper: helper1, optionalHelper: null, + increment(by) { this.count += by; }, + getValue() { return this.count; }, + setLabelElements(a, b) { }, getLabel() { return ""; }, + isEven() { return this.count % 2 === 0; }, + processGreeter(g) { return ""; }, createGreeter() { return new exports.Greeter("P1"); }, + processOptionalGreeter(g) { return ""; }, createOptionalGreeter() { return null; }, + handleAPIResult(r) { }, getAPIResult() { return null; } + }; + + const consumeResult = exports.consumeDataProcessorArrayType([jsProcessor1]); + assert.equal(consumeResult, 1); + + const processors = [jsProcessor1]; + const result = exports.roundTripDataProcessorArrayType(processors); + + assert.equal(result.length, 1); + assert.equal(result[0], jsProcessor1); + assert.equal(result[0].count, 1); + + helper1.release(); +} + /** @param {import('./../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */ function testProtocolSupport(exports) { let processorValue = 0; diff --git a/package-lock.json b/package-lock.json index e12af9c97..bf7f36315 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "prettier": "3.5.3", "rollup": "^4.37.0", "rollup-plugin-dts": "^6.2.1", + "tslib": "^2.8.1", "typescript": "^5.8.2" } }, @@ -507,12 +508,13 @@ } }, "node_modules/playwright": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz", - "integrity": "sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==", + "version": "1.55.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.55.1.tgz", + "integrity": "sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.52.0" + "playwright-core": "1.55.1" }, "bin": { "playwright": "cli.js" @@ -525,10 +527,11 @@ } }, "node_modules/playwright-core": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.52.0.tgz", - "integrity": "sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==", + "version": "1.55.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.55.1.tgz", + "integrity": "sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w==", "dev": true, + "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, @@ -579,6 +582,7 @@ "integrity": "sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "1.0.6" }, @@ -654,7 +658,6 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD", - "optional": true, "peer": true }, "node_modules/typescript": { @@ -663,6 +666,7 @@ "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index 96443ad9a..da7d5356d 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "prettier": "3.5.3", "rollup": "^4.37.0", "rollup-plugin-dts": "^6.2.1", + "tslib": "^2.8.1", "typescript": "^5.8.2" } }