diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e6da32aac..69f63a27c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,6 +3,9 @@ on: pull_request: push: branches: [main] +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} jobs: test: name: Build and Test @@ -11,22 +14,24 @@ jobs: entry: - os: ubuntu-22.04 toolchain: - download-url: https://download.swift.org/swift-6.0.2-release/ubuntu2204/swift-6.0.2-RELEASE/swift-6.0.2-RELEASE-ubuntu22.04.tar.gz + 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" - - os: ubuntu-22.04 + env: | + JAVASCRIPTKIT_DISABLE_TRACING_TRAIT=1 + - os: ubuntu-24.04 toolchain: - download-url: https://download.swift.org/swift-6.1-release/ubuntu2204/swift-6.1-RELEASE/swift-6.1-RELEASE-ubuntu22.04.tar.gz + 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 wasi-backend: Node - target: "wasm32-unknown-wasi" - - os: ubuntu-22.04 + target: "wasm32-unknown-wasip1" + - os: ubuntu-24.04 toolchain: - download-url: https://download.swift.org/development/ubuntu2204/swift-DEVELOPMENT-SNAPSHOT-2025-06-12-a/swift-DEVELOPMENT-SNAPSHOT-2025-06-12-a-ubuntu22.04.tar.gz + download-url: https://download.swift.org/swift-6.3-branch/ubuntu2404/swift-6.3-DEVELOPMENT-SNAPSHOT-2025-12-05-a/swift-6.3-DEVELOPMENT-SNAPSHOT-2025-12-05-a-ubuntu24.04.tar.gz wasi-backend: Node - target: "wasm32-unknown-wasi" + target: "wasm32-unknown-wasip1" - os: ubuntu-22.04 toolchain: - download-url: https://download.swift.org/development/ubuntu2204/swift-DEVELOPMENT-SNAPSHOT-2025-06-12-a/swift-DEVELOPMENT-SNAPSHOT-2025-06-12-a-ubuntu22.04.tar.gz + download-url: https://download.swift.org/development/ubuntu2204/swift-DEVELOPMENT-SNAPSHOT-2025-12-01-a/swift-DEVELOPMENT-SNAPSHOT-2025-12-01-a-ubuntu22.04.tar.gz wasi-backend: Node target: "wasm32-unknown-wasip1-threads" @@ -35,7 +40,13 @@ jobs: JAVASCRIPTKIT_WASI_BACKEND: ${{ matrix.entry.wasi-backend }} steps: - name: Checkout - uses: actions/checkout@v5 + 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 }} @@ -46,7 +57,7 @@ jobs: - name: Configure environment variables run: | echo "SWIFT_SDK_ID=${{ steps.setup-swiftwasm.outputs.swift-sdk-id }}" >> $GITHUB_ENV - echo "SWIFT_PATH=$(dirname $(which swiftc))" >> $GITHUB_ENV + echo "SWIFT_BIN_PATH=$(dirname $(which swiftc))" >> $GITHUB_ENV - run: make bootstrap - run: make unittest # Skip unit tests with uwasi because its proc_exit throws @@ -58,6 +69,37 @@ jobs: git diff --exit-code Sources/JavaScriptKit/Runtime - run: swift test --package-path ./Plugins/PackageToJS - run: swift test --package-path ./Plugins/BridgeJS + - name: Validate BridgeJS TypeScript declarations + run: npm run check:bridgejs-dts + + test-bridgejs-against-swift-versions: + name: Test BridgeJS against Swift versions + 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@v6 + with: + node-version: '20' + - name: Install TypeScript + run: npm install + - name: Validate BridgeJS TypeScript declarations + run: npm run check:bridgejs-dts + - name: Run BridgeJS tests + # NOTE: Seems like the prebuilt SwiftSyntax binaries are not compatible with + # non-macro dependents, so disable experimental prebuilts for now. + 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 @@ -69,17 +111,30 @@ jobs: xcode: Xcode_16.4 runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 + - run: swift build --product BridgeJSTool + env: + DEVELOPER_DIR: /Applications/${{ matrix.xcode }}.app/Contents/Developer/ - run: swift build --package-path ./Examples/Basic env: DEVELOPER_DIR: /Applications/${{ matrix.xcode }}.app/Contents/Developer/ + prettier: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-node@v6 + with: + node-version: '20' + - run: npm install + - run: npx prettier --check Runtime/src + format: runs-on: ubuntu-latest container: image: swift:6.1.2 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: ./Utilities/format.swift - name: Check for formatting changes run: | @@ -92,10 +147,10 @@ jobs: check-bridgejs-generated: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: ./.github/actions/install-swift with: - download-url: https://download.swift.org/development/ubuntu2204/swift-DEVELOPMENT-SNAPSHOT-2025-06-12-a/swift-DEVELOPMENT-SNAPSHOT-2025-06-12-a-ubuntu22.04.tar.gz + download-url: https://download.swift.org/development/ubuntu2204/swift-DEVELOPMENT-SNAPSHOT-2025-09-14-a/swift-DEVELOPMENT-SNAPSHOT-2025-09-14-a-ubuntu22.04.tar.gz - run: make bootstrap - run: ./Utilities/bridge-js-generate.sh - name: Check if BridgeJS generated files are up-to-date @@ -109,25 +164,26 @@ jobs: build-examples: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: ./.github/actions/install-swift with: - download-url: https://download.swift.org/development/ubuntu2204/swift-DEVELOPMENT-SNAPSHOT-2025-06-12-a/swift-DEVELOPMENT-SNAPSHOT-2025-06-12-a-ubuntu22.04.tar.gz + download-url: https://download.swift.org/development/ubuntu2204/swift-DEVELOPMENT-SNAPSHOT-2026-02-02-a/swift-DEVELOPMENT-SNAPSHOT-2026-02-02-a-ubuntu22.04.tar.gz - uses: swiftwasm/setup-swiftwasm@v2 - id: setup-wasm32-unknown-wasi - with: { target: wasm32-unknown-wasi } + id: setup-wasm32-unknown-wasip1 + with: { target: wasm32-unknown-wasip1 } - uses: swiftwasm/setup-swiftwasm@v2 id: setup-wasm32-unknown-wasip1-threads with: { target: wasm32-unknown-wasip1-threads } - run: ./Utilities/build-examples.sh env: SWIFT_SDK_ID_wasm32_unknown_wasip1_threads: ${{ steps.setup-wasm32-unknown-wasip1-threads.outputs.swift-sdk-id }} - SWIFT_SDK_ID_wasm32_unknown_wasi: ${{ steps.setup-wasm32-unknown-wasi.outputs.swift-sdk-id }} + SWIFT_SDK_ID_wasm32_unknown_wasip1: ${{ steps.setup-wasm32-unknown-wasip1.outputs.swift-sdk-id }} + - run: ./Utilities/prepare-gh-pages.sh - name: Upload static files as artifact id: deployment - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@v4 with: - path: Examples/ + path: ./_site deploy-examples: runs-on: ubuntu-latest if: github.event_name == 'push' && github.ref == 'refs/heads/main' diff --git a/.gitignore b/.gitignore index a62100fde..61397cf5b 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,23 @@ xcuserdata/ Examples/*/Bundle Examples/*/package-lock.json Package.resolved -Plugins/BridgeJS/Sources/JavaScript/package-lock.json +Plugins/BridgeJS/Sources/TS2Swift/JavaScript/package-lock.json Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/**/*.actual bridge-js.config.local.json +_site/ + +# AI coding agent config files +AGENTS.md +CLAUDE.md +GEMINI.md +.claude/ +.opencode/ +.cursor/ +.cursorrules +.codex/ +.aider* +.cline/ +.clinerules +.windsurf/ +.windsurfrules +.codeiumignore diff --git a/Benchmarks/README.md b/Benchmarks/README.md index eeafc395a..65d867eba 100644 --- a/Benchmarks/README.md +++ b/Benchmarks/README.md @@ -7,7 +7,7 @@ This directory contains performance benchmarks for JavaScriptKit. Before running the benchmarks, you need to build the test suite: ```bash -JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --swift-sdk $SWIFT_SDK_ID js -c release +swift package --swift-sdk $SWIFT_SDK_ID js -c release ``` ## Running Benchmarks @@ -27,4 +27,11 @@ node run.js --adaptive --output=stable-results.json # Run benchmarks and compare with previous results node run.js --baseline=previous-results.json + +# Run only a subset of benchmarks +# Substring match +node run.js --filter=Call +# Regex (with flags) +node run.js --filter=/^Property access\// +node run.js --filter=/string/i ``` diff --git a/Benchmarks/Sources/Benchmarks.swift b/Benchmarks/Sources/Benchmarks.swift index 155acae16..59da8c96c 100644 --- a/Benchmarks/Sources/Benchmarks.swift +++ b/Benchmarks/Sources/Benchmarks.swift @@ -14,7 +14,374 @@ class Benchmark { body() return .undefined } - benchmarkRunner("\(title)/\(name)", jsBody) + try! benchmarkRunner("\(title)/\(name)", jsBody) + } +} + +@JS enum APIResult { + case success(String) + case failure(Int) + case flag(Bool) + case rate(Float) + case precise(Double) + case info +} + +@JS class EnumRoundtrip { + @JS init() {} + + @JS func take(_ value: APIResult) {} + @JS func makeSuccess() -> APIResult { + return .success("Hello, world") + } + @JS func makeFailure() -> APIResult { + return .failure(42) + } + @JS func makeFlag() -> APIResult { + return .flag(true) + } + @JS func makeRate() -> APIResult { + return .rate(0.5) + } + @JS func makePrecise() -> APIResult { + return .precise(0.5) + } + @JS func makeInfo() -> APIResult { + return .info + } + + @JS func roundtrip(_ result: APIResult) -> APIResult { + return result + } +} + +@JS +enum ComplexResult { + case success(String) + case error(String, Int) + case location(Double, Double, String) + case status(Bool, Int, String) + case coordinates(Double, Double, Double) + case comprehensive(Bool, Bool, Int, Int, Double, Double, String, String, String) + case info +} + +@JS class ComplexResultRoundtrip { + @JS init() {} + + @JS func take(_ value: ComplexResult) {} + + @JS func makeSuccess() -> ComplexResult { + return .success("Hello, world") + } + + @JS func makeError() -> ComplexResult { + return .error("Network timeout", 503) + } + + @JS func makeLocation() -> ComplexResult { + return .location(37.7749, -122.4194, "San Francisco") + } + + @JS func makeStatus() -> ComplexResult { + return .status(true, 200, "OK") + } + + @JS func makeCoordinates() -> ComplexResult { + return .coordinates(10.5, 20.3, 30.7) + } + + @JS func makeComprehensive() -> ComplexResult { + return .comprehensive(true, false, 42, 100, 3.14, 2.718, "Hello", "World", "Test") + } + + @JS func makeInfo() -> ComplexResult { + return .info + } + + @JS func roundtrip(_ result: ComplexResult) -> ComplexResult { + return result + } +} +@JS class StringRoundtrip { + @JS init() {} + @JS func take(_ value: String) {} + @JS func make() -> String { + return "Hello, world" + } +} + +@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 { + var name: String + var count: Int + var flag: Bool + var rate: Float + var precise: Double +} + +@JS struct Address { + var street: String + var city: String + var zipCode: Int +} + +@JS struct Person { + var name: String + var age: Int + var address: Address + var email: String? +} + +@JS struct ComplexStruct { + var id: Int + var title: String + var active: Bool + var score: Double + var tags: String + var metadata: String +} + +@JS class StructRoundtrip { + @JS init() {} + + @JS func takeSimple(_ value: SimpleStruct) {} + @JS func makeSimple() -> SimpleStruct { + return SimpleStruct(name: "Hello", count: 42, flag: true, rate: 0.5, precise: 3.14159) + } + @JS func roundtripSimple(_ value: SimpleStruct) -> SimpleStruct { + return value + } + + @JS func takeAddress(_ value: Address) {} + @JS func makeAddress() -> Address { + return Address(street: "123 Main St", city: "San Francisco", zipCode: 94102) + } + @JS func roundtripAddress(_ value: Address) -> Address { + return value + } + + @JS func takePerson(_ value: Person) {} + @JS func makePerson() -> Person { + return Person( + name: "John Doe", + age: 30, + address: Address(street: "456 Oak Ave", city: "New York", zipCode: 10001), + email: "john@example.com" + ) + } + @JS func roundtripPerson(_ value: Person) -> Person { + return value + } + + @JS func takeComplex(_ value: ComplexStruct) {} + @JS func makeComplex() -> ComplexStruct { + return ComplexStruct( + id: 12345, + title: "Test Item", + active: true, + score: 98.6, + tags: "swift,wasm,benchmark", + metadata: "{\"version\":1}" + ) + } + @JS func roundtripComplex(_ value: ComplexStruct) -> ComplexStruct { + return value + } +} + +// MARK: - Class vs Struct Comparison Tests + +@JS class SimpleClass { + @JS var name: String + @JS var count: Int + @JS var flag: Bool + @JS var rate: Float + @JS var precise: Double + + @JS init(name: String, count: Int, flag: Bool, rate: Float, precise: Double) { + self.name = name + self.count = count + self.flag = flag + self.rate = rate + self.precise = precise + } +} + +@JS class AddressClass { + @JS var street: String + @JS var city: String + @JS var zipCode: Int + + @JS init(street: String, city: String, zipCode: Int) { + self.street = street + self.city = city + self.zipCode = zipCode + } +} + +@JS class ClassRoundtrip { + @JS init() {} + + @JS func takeSimpleClass(_ value: SimpleClass) {} + @JS func makeSimpleClass() -> SimpleClass { + return SimpleClass(name: "Hello", count: 42, flag: true, rate: 0.5, precise: 3.14159) + } + @JS func roundtripSimpleClass(_ value: SimpleClass) -> SimpleClass { + return value + } + + @JS func takeAddressClass(_ value: AddressClass) {} + @JS func makeAddressClass() -> AddressClass { + return AddressClass(street: "123 Main St", city: "San Francisco", zipCode: 94102) + } + @JS func roundtripAddressClass(_ value: AddressClass) -> AddressClass { + return value + } +} + +// 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 } } @@ -24,13 +391,13 @@ class Benchmark { call.testSuite("JavaScript function call through Wasm import") { for _ in 0..<20_000_000 { - benchmarkHelperNoop() + try! benchmarkHelperNoop() } } call.testSuite("JavaScript function call through Wasm import with int") { for _ in 0..<10_000_000 { - benchmarkHelperNoopWithNumber(42) + try! benchmarkHelperNoopWithNumber(42) } } diff --git a/Benchmarks/Sources/Generated/BridgeJS.ImportTS.swift b/Benchmarks/Sources/Generated/BridgeJS.ImportTS.swift deleted file mode 100644 index 871938cfb..000000000 --- a/Benchmarks/Sources/Generated/BridgeJS.ImportTS.swift +++ /dev/null @@ -1,56 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -func benchmarkHelperNoop() throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Benchmarks", name: "bjs_benchmarkHelperNoop") - func bjs_benchmarkHelperNoop() -> Void - #else - func bjs_benchmarkHelperNoop() -> Void { - fatalError("Only available on WebAssembly") - } - #endif - bjs_benchmarkHelperNoop() - if let error = _swift_js_take_exception() { - throw error - } -} - -func benchmarkHelperNoopWithNumber(_ n: Double) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Benchmarks", name: "bjs_benchmarkHelperNoopWithNumber") - func bjs_benchmarkHelperNoopWithNumber(_ n: Float64) -> Void - #else - func bjs_benchmarkHelperNoopWithNumber(_ n: Float64) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - bjs_benchmarkHelperNoopWithNumber(n) - if let error = _swift_js_take_exception() { - throw error - } -} - -func benchmarkRunner(_ name: String, _ body: JSObject) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Benchmarks", name: "bjs_benchmarkRunner") - func bjs_benchmarkRunner(_ name: Int32, _ body: Int32) -> Void - #else - func bjs_benchmarkRunner(_ name: Int32, _ body: Int32) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - var name = name - let nameId = name.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_benchmarkRunner(nameId, Int32(bitPattern: body.id)) - if let error = _swift_js_take_exception() { - throw error - } -} \ No newline at end of file diff --git a/Benchmarks/Sources/Generated/BridgeJS.Macros.swift b/Benchmarks/Sources/Generated/BridgeJS.Macros.swift new file mode 100644 index 000000000..40fc29e91 --- /dev/null +++ b/Benchmarks/Sources/Generated/BridgeJS.Macros.swift @@ -0,0 +1,13 @@ +// 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(BridgeJS) import JavaScriptKit + +@JSFunction func benchmarkHelperNoop() throws(JSException) -> Void + +@JSFunction func benchmarkHelperNoopWithNumber(_ n: Double) throws(JSException) -> Void + +@JSFunction func benchmarkRunner(_ name: String, _ body: JSObject) throws(JSException) -> Void diff --git a/Benchmarks/Sources/Generated/BridgeJS.swift b/Benchmarks/Sources/Generated/BridgeJS.swift new file mode 100644 index 000000000..6ec87dca8 --- /dev/null +++ b/Benchmarks/Sources/Generated/BridgeJS.swift @@ -0,0 +1,1779 @@ +// bridge-js: skip +// 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(BridgeJS) import JavaScriptKit + +extension APIResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> APIResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(Int.bridgeJSStackPop()) + case 2: + return .flag(Bool.bridgeJSStackPop()) + case 3: + return .rate(Float.bridgeJSStackPop()) + case 4: + return .precise(Double.bridgeJSStackPop()) + case 5: + return .info + default: + fatalError("Unknown APIResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .failure(let param0): + param0.bridgeJSStackPush() + return Int32(1) + case .flag(let param0): + param0.bridgeJSStackPush() + return Int32(2) + case .rate(let param0): + param0.bridgeJSStackPush() + return Int32(3) + case .precise(let param0): + param0.bridgeJSStackPush() + return Int32(4) + case .info: + return Int32(5) + } + } +} + +extension ComplexResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> ComplexResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .error(String.bridgeJSStackPop(), Int.bridgeJSStackPop()) + case 2: + return .location(Double.bridgeJSStackPop(), Double.bridgeJSStackPop(), String.bridgeJSStackPop()) + case 3: + return .status(Bool.bridgeJSStackPop(), Int.bridgeJSStackPop(), String.bridgeJSStackPop()) + case 4: + return .coordinates(Double.bridgeJSStackPop(), Double.bridgeJSStackPop(), Double.bridgeJSStackPop()) + case 5: + return .comprehensive(Bool.bridgeJSStackPop(), Bool.bridgeJSStackPop(), Int.bridgeJSStackPop(), Int.bridgeJSStackPop(), Double.bridgeJSStackPop(), Double.bridgeJSStackPop(), String.bridgeJSStackPop(), String.bridgeJSStackPop(), String.bridgeJSStackPop()) + case 6: + return .info + default: + fatalError("Unknown ComplexResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .error(let param0, let param1): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + return Int32(1) + case .location(let param0, let param1, let param2): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + param2.bridgeJSStackPush() + return Int32(2) + case .status(let param0, let param1, let param2): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + param2.bridgeJSStackPush() + return Int32(3) + case .coordinates(let param0, let param1, let param2): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + param2.bridgeJSStackPush() + return Int32(4) + case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + param2.bridgeJSStackPush() + param3.bridgeJSStackPush() + param4.bridgeJSStackPush() + param5.bridgeJSStackPush() + param6.bridgeJSStackPush() + param7.bridgeJSStackPush() + param8.bridgeJSStackPush() + return Int32(5) + case .info: + return Int32(6) + } + } +} + +extension SimpleStruct: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> SimpleStruct { + let precise = Double.bridgeJSStackPop() + let rate = Float.bridgeJSStackPop() + let flag = Bool.bridgeJSStackPop() + let count = Int.bridgeJSStackPop() + let name = String.bridgeJSStackPop() + return SimpleStruct(name: name, count: count, flag: flag, rate: rate, precise: precise) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.name.bridgeJSStackPush() + self.count.bridgeJSStackPush() + self.flag.bridgeJSStackPush() + self.rate.bridgeJSStackPush() + self.precise.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_SimpleStruct(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> Address { + let zipCode = Int.bridgeJSStackPop() + let city = String.bridgeJSStackPop() + let street = String.bridgeJSStackPop() + return Address(street: street, city: city, zipCode: zipCode) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.street.bridgeJSStackPush() + self.city.bridgeJSStackPush() + self.zipCode.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Address(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> Person { + let email = Optional.bridgeJSStackPop() + let address = Address.bridgeJSStackPop() + let age = Int.bridgeJSStackPop() + let name = String.bridgeJSStackPop() + return Person(name: name, age: age, address: address, email: email) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.name.bridgeJSStackPush() + self.age.bridgeJSStackPush() + self.address.bridgeJSStackPush() + let __bjs_isSome_email = self.email != nil + if let __bjs_unwrapped_email = self.email { + __bjs_unwrapped_email.bridgeJSStackPush() + } + _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.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> ComplexStruct { + let metadata = String.bridgeJSStackPop() + let tags = String.bridgeJSStackPop() + let score = Double.bridgeJSStackPop() + let active = Bool.bridgeJSStackPop() + let title = String.bridgeJSStackPop() + let id = Int.bridgeJSStackPop() + return ComplexStruct(id: id, title: title, active: active, score: score, tags: tags, metadata: metadata) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.id.bridgeJSStackPush() + self.title.bridgeJSStackPush() + self.active.bridgeJSStackPush() + self.score.bridgeJSStackPush() + self.tags.bridgeJSStackPush() + self.metadata.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_ComplexStruct(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> Point { + let y = Double.bridgeJSStackPop() + let x = Double.bridgeJSStackPop() + return Point(x: x, y: y) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.x.bridgeJSStackPush() + self.y.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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") +public func _bjs_run() -> Void { + #if arch(wasm32) + run() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_init") +@_cdecl("bjs_EnumRoundtrip_init") +public func _bjs_EnumRoundtrip_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = EnumRoundtrip() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_take") +@_cdecl("bjs_EnumRoundtrip_take") +public func _bjs_EnumRoundtrip_take(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + EnumRoundtrip.bridgeJSLiftParameter(_self).take(_: APIResult.bridgeJSLiftParameter(value)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_makeSuccess") +@_cdecl("bjs_EnumRoundtrip_makeSuccess") +public func _bjs_EnumRoundtrip_makeSuccess(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = EnumRoundtrip.bridgeJSLiftParameter(_self).makeSuccess() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_makeFailure") +@_cdecl("bjs_EnumRoundtrip_makeFailure") +public func _bjs_EnumRoundtrip_makeFailure(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = EnumRoundtrip.bridgeJSLiftParameter(_self).makeFailure() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_makeFlag") +@_cdecl("bjs_EnumRoundtrip_makeFlag") +public func _bjs_EnumRoundtrip_makeFlag(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = EnumRoundtrip.bridgeJSLiftParameter(_self).makeFlag() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_makeRate") +@_cdecl("bjs_EnumRoundtrip_makeRate") +public func _bjs_EnumRoundtrip_makeRate(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = EnumRoundtrip.bridgeJSLiftParameter(_self).makeRate() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_makePrecise") +@_cdecl("bjs_EnumRoundtrip_makePrecise") +public func _bjs_EnumRoundtrip_makePrecise(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = EnumRoundtrip.bridgeJSLiftParameter(_self).makePrecise() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_makeInfo") +@_cdecl("bjs_EnumRoundtrip_makeInfo") +public func _bjs_EnumRoundtrip_makeInfo(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = EnumRoundtrip.bridgeJSLiftParameter(_self).makeInfo() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_roundtrip") +@_cdecl("bjs_EnumRoundtrip_roundtrip") +public func _bjs_EnumRoundtrip_roundtrip(_ _self: UnsafeMutableRawPointer, _ result: Int32) -> Void { + #if arch(wasm32) + let ret = EnumRoundtrip.bridgeJSLiftParameter(_self).roundtrip(_: APIResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_deinit") +@_cdecl("bjs_EnumRoundtrip_deinit") +public func _bjs_EnumRoundtrip_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension EnumRoundtrip: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_EnumRoundtrip_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "Benchmarks", name: "bjs_EnumRoundtrip_wrap") +fileprivate func _bjs_EnumRoundtrip_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_EnumRoundtrip_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_ComplexResultRoundtrip_init") +@_cdecl("bjs_ComplexResultRoundtrip_init") +public func _bjs_ComplexResultRoundtrip_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = ComplexResultRoundtrip() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_take") +@_cdecl("bjs_ComplexResultRoundtrip_take") +public func _bjs_ComplexResultRoundtrip_take(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + ComplexResultRoundtrip.bridgeJSLiftParameter(_self).take(_: ComplexResult.bridgeJSLiftParameter(value)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_makeSuccess") +@_cdecl("bjs_ComplexResultRoundtrip_makeSuccess") +public func _bjs_ComplexResultRoundtrip_makeSuccess(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ComplexResultRoundtrip.bridgeJSLiftParameter(_self).makeSuccess() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_makeError") +@_cdecl("bjs_ComplexResultRoundtrip_makeError") +public func _bjs_ComplexResultRoundtrip_makeError(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ComplexResultRoundtrip.bridgeJSLiftParameter(_self).makeError() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_makeLocation") +@_cdecl("bjs_ComplexResultRoundtrip_makeLocation") +public func _bjs_ComplexResultRoundtrip_makeLocation(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ComplexResultRoundtrip.bridgeJSLiftParameter(_self).makeLocation() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_makeStatus") +@_cdecl("bjs_ComplexResultRoundtrip_makeStatus") +public func _bjs_ComplexResultRoundtrip_makeStatus(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ComplexResultRoundtrip.bridgeJSLiftParameter(_self).makeStatus() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_makeCoordinates") +@_cdecl("bjs_ComplexResultRoundtrip_makeCoordinates") +public func _bjs_ComplexResultRoundtrip_makeCoordinates(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ComplexResultRoundtrip.bridgeJSLiftParameter(_self).makeCoordinates() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_makeComprehensive") +@_cdecl("bjs_ComplexResultRoundtrip_makeComprehensive") +public func _bjs_ComplexResultRoundtrip_makeComprehensive(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ComplexResultRoundtrip.bridgeJSLiftParameter(_self).makeComprehensive() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_makeInfo") +@_cdecl("bjs_ComplexResultRoundtrip_makeInfo") +public func _bjs_ComplexResultRoundtrip_makeInfo(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ComplexResultRoundtrip.bridgeJSLiftParameter(_self).makeInfo() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_roundtrip") +@_cdecl("bjs_ComplexResultRoundtrip_roundtrip") +public func _bjs_ComplexResultRoundtrip_roundtrip(_ _self: UnsafeMutableRawPointer, _ result: Int32) -> Void { + #if arch(wasm32) + let ret = ComplexResultRoundtrip.bridgeJSLiftParameter(_self).roundtrip(_: ComplexResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_deinit") +@_cdecl("bjs_ComplexResultRoundtrip_deinit") +public func _bjs_ComplexResultRoundtrip_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension ComplexResultRoundtrip: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_ComplexResultRoundtrip_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "Benchmarks", name: "bjs_ComplexResultRoundtrip_wrap") +fileprivate func _bjs_ComplexResultRoundtrip_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_ComplexResultRoundtrip_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_StringRoundtrip_init") +@_cdecl("bjs_StringRoundtrip_init") +public func _bjs_StringRoundtrip_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = StringRoundtrip() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringRoundtrip_take") +@_cdecl("bjs_StringRoundtrip_take") +public func _bjs_StringRoundtrip_take(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + StringRoundtrip.bridgeJSLiftParameter(_self).take(_: String.bridgeJSLiftParameter(valueBytes, valueLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringRoundtrip_make") +@_cdecl("bjs_StringRoundtrip_make") +public func _bjs_StringRoundtrip_make(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = StringRoundtrip.bridgeJSLiftParameter(_self).make() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringRoundtrip_deinit") +@_cdecl("bjs_StringRoundtrip_deinit") +public func _bjs_StringRoundtrip_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension StringRoundtrip: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_StringRoundtrip_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "Benchmarks", name: "bjs_StringRoundtrip_wrap") +fileprivate func _bjs_StringRoundtrip_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_StringRoundtrip_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#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 { + #if arch(wasm32) + let ret = StructRoundtrip() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StructRoundtrip_takeSimple") +@_cdecl("bjs_StructRoundtrip_takeSimple") +public func _bjs_StructRoundtrip_takeSimple(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + StructRoundtrip.bridgeJSLiftParameter(_self).takeSimple(_: SimpleStruct.bridgeJSLiftParameter()) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StructRoundtrip_makeSimple") +@_cdecl("bjs_StructRoundtrip_makeSimple") +public func _bjs_StructRoundtrip_makeSimple(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = StructRoundtrip.bridgeJSLiftParameter(_self).makeSimple() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StructRoundtrip_roundtripSimple") +@_cdecl("bjs_StructRoundtrip_roundtripSimple") +public func _bjs_StructRoundtrip_roundtripSimple(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = StructRoundtrip.bridgeJSLiftParameter(_self).roundtripSimple(_: SimpleStruct.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StructRoundtrip_takeAddress") +@_cdecl("bjs_StructRoundtrip_takeAddress") +public func _bjs_StructRoundtrip_takeAddress(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + StructRoundtrip.bridgeJSLiftParameter(_self).takeAddress(_: Address.bridgeJSLiftParameter()) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StructRoundtrip_makeAddress") +@_cdecl("bjs_StructRoundtrip_makeAddress") +public func _bjs_StructRoundtrip_makeAddress(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = StructRoundtrip.bridgeJSLiftParameter(_self).makeAddress() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StructRoundtrip_roundtripAddress") +@_cdecl("bjs_StructRoundtrip_roundtripAddress") +public func _bjs_StructRoundtrip_roundtripAddress(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = StructRoundtrip.bridgeJSLiftParameter(_self).roundtripAddress(_: Address.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StructRoundtrip_takePerson") +@_cdecl("bjs_StructRoundtrip_takePerson") +public func _bjs_StructRoundtrip_takePerson(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + StructRoundtrip.bridgeJSLiftParameter(_self).takePerson(_: Person.bridgeJSLiftParameter()) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StructRoundtrip_makePerson") +@_cdecl("bjs_StructRoundtrip_makePerson") +public func _bjs_StructRoundtrip_makePerson(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = StructRoundtrip.bridgeJSLiftParameter(_self).makePerson() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StructRoundtrip_roundtripPerson") +@_cdecl("bjs_StructRoundtrip_roundtripPerson") +public func _bjs_StructRoundtrip_roundtripPerson(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = StructRoundtrip.bridgeJSLiftParameter(_self).roundtripPerson(_: Person.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StructRoundtrip_takeComplex") +@_cdecl("bjs_StructRoundtrip_takeComplex") +public func _bjs_StructRoundtrip_takeComplex(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + StructRoundtrip.bridgeJSLiftParameter(_self).takeComplex(_: ComplexStruct.bridgeJSLiftParameter()) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StructRoundtrip_makeComplex") +@_cdecl("bjs_StructRoundtrip_makeComplex") +public func _bjs_StructRoundtrip_makeComplex(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = StructRoundtrip.bridgeJSLiftParameter(_self).makeComplex() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StructRoundtrip_roundtripComplex") +@_cdecl("bjs_StructRoundtrip_roundtripComplex") +public func _bjs_StructRoundtrip_roundtripComplex(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = StructRoundtrip.bridgeJSLiftParameter(_self).roundtripComplex(_: ComplexStruct.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StructRoundtrip_deinit") +@_cdecl("bjs_StructRoundtrip_deinit") +public func _bjs_StructRoundtrip_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension StructRoundtrip: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_StructRoundtrip_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "Benchmarks", name: "bjs_StructRoundtrip_wrap") +fileprivate func _bjs_StructRoundtrip_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_StructRoundtrip_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_SimpleClass_init") +@_cdecl("bjs_SimpleClass_init") +public func _bjs_SimpleClass_init(_ nameBytes: Int32, _ nameLength: Int32, _ count: Int32, _ flag: Int32, _ rate: Float32, _ precise: Float64) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = SimpleClass(name: String.bridgeJSLiftParameter(nameBytes, nameLength), count: Int.bridgeJSLiftParameter(count), flag: Bool.bridgeJSLiftParameter(flag), rate: Float.bridgeJSLiftParameter(rate), precise: Double.bridgeJSLiftParameter(precise)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SimpleClass_name_get") +@_cdecl("bjs_SimpleClass_name_get") +public func _bjs_SimpleClass_name_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = SimpleClass.bridgeJSLiftParameter(_self).name + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SimpleClass_name_set") +@_cdecl("bjs_SimpleClass_name_set") +public func _bjs_SimpleClass_name_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + SimpleClass.bridgeJSLiftParameter(_self).name = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SimpleClass_count_get") +@_cdecl("bjs_SimpleClass_count_get") +public func _bjs_SimpleClass_count_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = SimpleClass.bridgeJSLiftParameter(_self).count + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SimpleClass_count_set") +@_cdecl("bjs_SimpleClass_count_set") +public func _bjs_SimpleClass_count_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + SimpleClass.bridgeJSLiftParameter(_self).count = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SimpleClass_flag_get") +@_cdecl("bjs_SimpleClass_flag_get") +public func _bjs_SimpleClass_flag_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = SimpleClass.bridgeJSLiftParameter(_self).flag + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SimpleClass_flag_set") +@_cdecl("bjs_SimpleClass_flag_set") +public func _bjs_SimpleClass_flag_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + SimpleClass.bridgeJSLiftParameter(_self).flag = Bool.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SimpleClass_rate_get") +@_cdecl("bjs_SimpleClass_rate_get") +public func _bjs_SimpleClass_rate_get(_ _self: UnsafeMutableRawPointer) -> Float32 { + #if arch(wasm32) + let ret = SimpleClass.bridgeJSLiftParameter(_self).rate + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SimpleClass_rate_set") +@_cdecl("bjs_SimpleClass_rate_set") +public func _bjs_SimpleClass_rate_set(_ _self: UnsafeMutableRawPointer, _ value: Float32) -> Void { + #if arch(wasm32) + SimpleClass.bridgeJSLiftParameter(_self).rate = Float.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SimpleClass_precise_get") +@_cdecl("bjs_SimpleClass_precise_get") +public func _bjs_SimpleClass_precise_get(_ _self: UnsafeMutableRawPointer) -> Float64 { + #if arch(wasm32) + let ret = SimpleClass.bridgeJSLiftParameter(_self).precise + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SimpleClass_precise_set") +@_cdecl("bjs_SimpleClass_precise_set") +public func _bjs_SimpleClass_precise_set(_ _self: UnsafeMutableRawPointer, _ value: Float64) -> Void { + #if arch(wasm32) + SimpleClass.bridgeJSLiftParameter(_self).precise = Double.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SimpleClass_deinit") +@_cdecl("bjs_SimpleClass_deinit") +public func _bjs_SimpleClass_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension SimpleClass: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_SimpleClass_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "Benchmarks", name: "bjs_SimpleClass_wrap") +fileprivate func _bjs_SimpleClass_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_SimpleClass_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_AddressClass_init") +@_cdecl("bjs_AddressClass_init") +public func _bjs_AddressClass_init(_ streetBytes: Int32, _ streetLength: Int32, _ cityBytes: Int32, _ cityLength: Int32, _ zipCode: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = AddressClass(street: String.bridgeJSLiftParameter(streetBytes, streetLength), city: String.bridgeJSLiftParameter(cityBytes, cityLength), zipCode: Int.bridgeJSLiftParameter(zipCode)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_AddressClass_street_get") +@_cdecl("bjs_AddressClass_street_get") +public func _bjs_AddressClass_street_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = AddressClass.bridgeJSLiftParameter(_self).street + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_AddressClass_street_set") +@_cdecl("bjs_AddressClass_street_set") +public func _bjs_AddressClass_street_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + AddressClass.bridgeJSLiftParameter(_self).street = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_AddressClass_city_get") +@_cdecl("bjs_AddressClass_city_get") +public func _bjs_AddressClass_city_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = AddressClass.bridgeJSLiftParameter(_self).city + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_AddressClass_city_set") +@_cdecl("bjs_AddressClass_city_set") +public func _bjs_AddressClass_city_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + AddressClass.bridgeJSLiftParameter(_self).city = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_AddressClass_zipCode_get") +@_cdecl("bjs_AddressClass_zipCode_get") +public func _bjs_AddressClass_zipCode_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = AddressClass.bridgeJSLiftParameter(_self).zipCode + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_AddressClass_zipCode_set") +@_cdecl("bjs_AddressClass_zipCode_set") +public func _bjs_AddressClass_zipCode_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + AddressClass.bridgeJSLiftParameter(_self).zipCode = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_AddressClass_deinit") +@_cdecl("bjs_AddressClass_deinit") +public func _bjs_AddressClass_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension AddressClass: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_AddressClass_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "Benchmarks", name: "bjs_AddressClass_wrap") +fileprivate func _bjs_AddressClass_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_AddressClass_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_ClassRoundtrip_init") +@_cdecl("bjs_ClassRoundtrip_init") +public func _bjs_ClassRoundtrip_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = ClassRoundtrip() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClassRoundtrip_takeSimpleClass") +@_cdecl("bjs_ClassRoundtrip_takeSimpleClass") +public func _bjs_ClassRoundtrip_takeSimpleClass(_ _self: UnsafeMutableRawPointer, _ value: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + ClassRoundtrip.bridgeJSLiftParameter(_self).takeSimpleClass(_: SimpleClass.bridgeJSLiftParameter(value)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClassRoundtrip_makeSimpleClass") +@_cdecl("bjs_ClassRoundtrip_makeSimpleClass") +public func _bjs_ClassRoundtrip_makeSimpleClass(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = ClassRoundtrip.bridgeJSLiftParameter(_self).makeSimpleClass() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClassRoundtrip_roundtripSimpleClass") +@_cdecl("bjs_ClassRoundtrip_roundtripSimpleClass") +public func _bjs_ClassRoundtrip_roundtripSimpleClass(_ _self: UnsafeMutableRawPointer, _ value: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = ClassRoundtrip.bridgeJSLiftParameter(_self).roundtripSimpleClass(_: SimpleClass.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClassRoundtrip_takeAddressClass") +@_cdecl("bjs_ClassRoundtrip_takeAddressClass") +public func _bjs_ClassRoundtrip_takeAddressClass(_ _self: UnsafeMutableRawPointer, _ value: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + ClassRoundtrip.bridgeJSLiftParameter(_self).takeAddressClass(_: AddressClass.bridgeJSLiftParameter(value)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClassRoundtrip_makeAddressClass") +@_cdecl("bjs_ClassRoundtrip_makeAddressClass") +public func _bjs_ClassRoundtrip_makeAddressClass(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = ClassRoundtrip.bridgeJSLiftParameter(_self).makeAddressClass() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClassRoundtrip_roundtripAddressClass") +@_cdecl("bjs_ClassRoundtrip_roundtripAddressClass") +public func _bjs_ClassRoundtrip_roundtripAddressClass(_ _self: UnsafeMutableRawPointer, _ value: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = ClassRoundtrip.bridgeJSLiftParameter(_self).roundtripAddressClass(_: AddressClass.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClassRoundtrip_deinit") +@_cdecl("bjs_ClassRoundtrip_deinit") +public func _bjs_ClassRoundtrip_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension ClassRoundtrip: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_ClassRoundtrip_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "Benchmarks", name: "bjs_ClassRoundtrip_wrap") +fileprivate func _bjs_ClassRoundtrip_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_ClassRoundtrip_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#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(_: [Int].bridgeJSStackPop()) + #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() + ret.bridgeJSStackPush() + #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(_: [Int].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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() + ret.bridgeJSStackPush() + #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(_: [Double].bridgeJSStackPop()) + #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() + ret.bridgeJSStackPush() + #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(_: [Double].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [String].bridgeJSStackPop()) + #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() + ret.bridgeJSStackPush() + #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(_: [String].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [Point].bridgeJSStackPop()) + #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() + ret.bridgeJSStackPush() + #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(_: [Point].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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() + ret.bridgeJSStackPush() + #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(_: [[Int]].bridgeJSStackPop()) + #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() + ret.bridgeJSStackPush() + #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(_: [[Int]].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [[Point]].bridgeJSStackPop()) + #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() + ret.bridgeJSStackPush() + #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(_: [[Point]].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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.bridgeJSStackPop()) + } + __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 { + __bjs_unwrapped_ret_elem.bridgeJSStackPush() + } + _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.bridgeJSStackPop()) + } + __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.bridgeJSStackPush() + } + _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.bridgeJSStackPop()) + } + __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 { + __bjs_elem_ret.bridgeJSStackPush() + } + _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.bridgeJSStackPop()) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + __bjs_elem_ret.bridgeJSStackPush() + } + _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) -> Void { + #if arch(wasm32) + ArrayRoundtrip.bridgeJSLiftParameter(_self).takeOptionalArray(_: Optional<[Int]>.bridgeJSLiftParameter()) + #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() + ret.bridgeJSStackPush() + #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() + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayRoundtrip_roundtripOptionalArray") +@_cdecl("bjs_ArrayRoundtrip_roundtripOptionalArray") +public func _bjs_ArrayRoundtrip_roundtripOptionalArray(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).roundtripOptionalArray(_: Optional<[Int]>.bridgeJSLiftParameter()) + ret.bridgeJSStackPush() + #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 +#else +fileprivate func bjs_benchmarkHelperNoop() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$benchmarkHelperNoop() throws(JSException) -> Void { + bjs_benchmarkHelperNoop() + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "Benchmarks", name: "bjs_benchmarkHelperNoopWithNumber") +fileprivate func bjs_benchmarkHelperNoopWithNumber(_ n: Float64) -> Void +#else +fileprivate func bjs_benchmarkHelperNoopWithNumber(_ n: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$benchmarkHelperNoopWithNumber(_ n: Double) throws(JSException) -> Void { + let nValue = n.bridgeJSLowerParameter() + bjs_benchmarkHelperNoopWithNumber(nValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "Benchmarks", name: "bjs_benchmarkRunner") +fileprivate func bjs_benchmarkRunner(_ name: Int32, _ body: Int32) -> Void +#else +fileprivate func bjs_benchmarkRunner(_ name: Int32, _ body: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$benchmarkRunner(_ name: String, _ body: JSObject) throws(JSException) -> Void { + let nameValue = name.bridgeJSLowerParameter() + let bodyValue = body.bridgeJSLowerParameter() + bjs_benchmarkRunner(nameValue, bodyValue) + if let error = _swift_js_take_exception() { + throw error + } +} \ No newline at end of file diff --git a/Benchmarks/Sources/Generated/JavaScript/BridgeJS.ExportSwift.json b/Benchmarks/Sources/Generated/JavaScript/BridgeJS.ExportSwift.json deleted file mode 100644 index 2e94644d8..000000000 --- a/Benchmarks/Sources/Generated/JavaScript/BridgeJS.ExportSwift.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "classes" : [ - - ], - "functions" : [ - { - "abiName" : "bjs_run", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "run", - "parameters" : [ - - ], - "returnType" : { - "void" : { - - } - } - } - ], - "moduleName" : "Benchmarks" -} \ No newline at end of file diff --git a/Benchmarks/Sources/Generated/JavaScript/BridgeJS.ImportTS.json b/Benchmarks/Sources/Generated/JavaScript/BridgeJS.ImportTS.json deleted file mode 100644 index 366342bbc..000000000 --- a/Benchmarks/Sources/Generated/JavaScript/BridgeJS.ImportTS.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "children" : [ - { - "functions" : [ - { - "name" : "benchmarkHelperNoop", - "parameters" : [ - - ], - "returnType" : { - "void" : { - - } - } - }, - { - "name" : "benchmarkHelperNoopWithNumber", - "parameters" : [ - { - "name" : "n", - "type" : { - "double" : { - - } - } - } - ], - "returnType" : { - "void" : { - - } - } - }, - { - "name" : "benchmarkRunner", - "parameters" : [ - { - "name" : "name", - "type" : { - "string" : { - - } - } - }, - { - "name" : "body", - "type" : { - "jsObject" : { - - } - } - } - ], - "returnType" : { - "void" : { - - } - } - } - ], - "types" : [ - - ] - } - ], - "moduleName" : "Benchmarks" -} \ No newline at end of file diff --git a/Benchmarks/Sources/Generated/JavaScript/BridgeJS.json b/Benchmarks/Sources/Generated/JavaScript/BridgeJS.json new file mode 100644 index 000000000..eacd18cb3 --- /dev/null +++ b/Benchmarks/Sources/Generated/JavaScript/BridgeJS.json @@ -0,0 +1,2805 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_EnumRoundtrip_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_EnumRoundtrip_take", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "take", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_EnumRoundtrip_makeSuccess", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeSuccess", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_EnumRoundtrip_makeFailure", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeFailure", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_EnumRoundtrip_makeFlag", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeFlag", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_EnumRoundtrip_makeRate", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeRate", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_EnumRoundtrip_makePrecise", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makePrecise", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_EnumRoundtrip_makeInfo", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeInfo", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_EnumRoundtrip_roundtrip", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtrip", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + ], + "name" : "EnumRoundtrip", + "properties" : [ + + ], + "swiftCallName" : "EnumRoundtrip" + }, + { + "constructor" : { + "abiName" : "bjs_ComplexResultRoundtrip_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_ComplexResultRoundtrip_take", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "take", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_ComplexResultRoundtrip_makeSuccess", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeSuccess", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_ComplexResultRoundtrip_makeError", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeError", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_ComplexResultRoundtrip_makeLocation", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeLocation", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_ComplexResultRoundtrip_makeStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeStatus", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_ComplexResultRoundtrip_makeCoordinates", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeCoordinates", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_ComplexResultRoundtrip_makeComprehensive", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeComprehensive", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_ComplexResultRoundtrip_makeInfo", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeInfo", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_ComplexResultRoundtrip_roundtrip", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtrip", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + } + ], + "name" : "ComplexResultRoundtrip", + "properties" : [ + + ], + "swiftCallName" : "ComplexResultRoundtrip" + }, + { + "constructor" : { + "abiName" : "bjs_StringRoundtrip_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_StringRoundtrip_take", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "take", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_StringRoundtrip_make", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "make", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "StringRoundtrip", + "properties" : [ + + ], + "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" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_OptionalReturnRoundtrip_makeIntNone", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeIntNone", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_OptionalReturnRoundtrip_makeBoolSome", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeBoolSome", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_OptionalReturnRoundtrip_makeBoolNone", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeBoolNone", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_OptionalReturnRoundtrip_makeDoubleSome", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeDoubleSome", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_OptionalReturnRoundtrip_makeDoubleNone", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeDoubleNone", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_OptionalReturnRoundtrip_makeStringSome", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeStringSome", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_OptionalReturnRoundtrip_makeStringNone", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeStringNone", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "name" : "OptionalReturnRoundtrip", + "properties" : [ + + ], + "swiftCallName" : "OptionalReturnRoundtrip" + }, + { + "constructor" : { + "abiName" : "bjs_StructRoundtrip_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_StructRoundtrip_takeSimple", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeSimple", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftStruct" : { + "_0" : "SimpleStruct" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_StructRoundtrip_makeSimple", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeSimple", + "parameters" : [ + + ], + "returnType" : { + "swiftStruct" : { + "_0" : "SimpleStruct" + } + } + }, + { + "abiName" : "bjs_StructRoundtrip_roundtripSimple", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripSimple", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftStruct" : { + "_0" : "SimpleStruct" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "SimpleStruct" + } + } + }, + { + "abiName" : "bjs_StructRoundtrip_takeAddress", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeAddress", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftStruct" : { + "_0" : "Address" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_StructRoundtrip_makeAddress", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeAddress", + "parameters" : [ + + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Address" + } + } + }, + { + "abiName" : "bjs_StructRoundtrip_roundtripAddress", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripAddress", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftStruct" : { + "_0" : "Address" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Address" + } + } + }, + { + "abiName" : "bjs_StructRoundtrip_takePerson", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takePerson", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftStruct" : { + "_0" : "Person" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_StructRoundtrip_makePerson", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makePerson", + "parameters" : [ + + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Person" + } + } + }, + { + "abiName" : "bjs_StructRoundtrip_roundtripPerson", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripPerson", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftStruct" : { + "_0" : "Person" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Person" + } + } + }, + { + "abiName" : "bjs_StructRoundtrip_takeComplex", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeComplex", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftStruct" : { + "_0" : "ComplexStruct" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_StructRoundtrip_makeComplex", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeComplex", + "parameters" : [ + + ], + "returnType" : { + "swiftStruct" : { + "_0" : "ComplexStruct" + } + } + }, + { + "abiName" : "bjs_StructRoundtrip_roundtripComplex", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripComplex", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftStruct" : { + "_0" : "ComplexStruct" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "ComplexStruct" + } + } + } + ], + "name" : "StructRoundtrip", + "properties" : [ + + ], + "swiftCallName" : "StructRoundtrip" + }, + { + "constructor" : { + "abiName" : "bjs_SimpleClass_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "label" : "count", + "name" : "count", + "type" : { + "int" : { + + } + } + }, + { + "label" : "flag", + "name" : "flag", + "type" : { + "bool" : { + + } + } + }, + { + "label" : "rate", + "name" : "rate", + "type" : { + "float" : { + + } + } + }, + { + "label" : "precise", + "name" : "precise", + "type" : { + "double" : { + + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "SimpleClass", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "count", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "flag", + "type" : { + "bool" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "rate", + "type" : { + "float" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "precise", + "type" : { + "double" : { + + } + } + } + ], + "swiftCallName" : "SimpleClass" + }, + { + "constructor" : { + "abiName" : "bjs_AddressClass_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "street", + "name" : "street", + "type" : { + "string" : { + + } + } + }, + { + "label" : "city", + "name" : "city", + "type" : { + "string" : { + + } + } + }, + { + "label" : "zipCode", + "name" : "zipCode", + "type" : { + "int" : { + + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "AddressClass", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "street", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "city", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "zipCode", + "type" : { + "int" : { + + } + } + } + ], + "swiftCallName" : "AddressClass" + }, + { + "constructor" : { + "abiName" : "bjs_ClassRoundtrip_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_ClassRoundtrip_takeSimpleClass", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeSimpleClass", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftHeapObject" : { + "_0" : "SimpleClass" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_ClassRoundtrip_makeSimpleClass", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeSimpleClass", + "parameters" : [ + + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "SimpleClass" + } + } + }, + { + "abiName" : "bjs_ClassRoundtrip_roundtripSimpleClass", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripSimpleClass", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftHeapObject" : { + "_0" : "SimpleClass" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "SimpleClass" + } + } + }, + { + "abiName" : "bjs_ClassRoundtrip_takeAddressClass", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeAddressClass", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftHeapObject" : { + "_0" : "AddressClass" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_ClassRoundtrip_makeAddressClass", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeAddressClass", + "parameters" : [ + + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "AddressClass" + } + } + }, + { + "abiName" : "bjs_ClassRoundtrip_roundtripAddressClass", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripAddressClass", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftHeapObject" : { + "_0" : "AddressClass" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "AddressClass" + } + } + } + ], + "name" : "ClassRoundtrip", + "properties" : [ + + ], + "swiftCallName" : "ClassRoundtrip" + }, + { + "constructor" : { + "abiName" : "bjs_ArrayRoundtrip_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_ArrayRoundtrip_takeIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeIntArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_makeIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeIntArray", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_roundtripIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripIntArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_makeIntArrayLarge", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeIntArrayLarge", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "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" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_makeOptionalIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeOptionalIntArray", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_roundtripOptionalIntArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalIntArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_takeOptionalPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeOptionalPointArray", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_makeOptionalPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeOptionalPointArray", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_roundtripOptionalPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalPointArray", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_takeOptionalArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeOptionalArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_makeOptionalArraySome", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeOptionalArraySome", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_makeOptionalArrayNone", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeOptionalArrayNone", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_ArrayRoundtrip_roundtripOptionalArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "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" : [ + + ], + "name" : "info" + } + ], + "emitStyle" : "const", + "name" : "APIResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "APIResult", + "tsFullPath" : "APIResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "error" + }, + { + "associatedValues" : [ + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "location" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "status" + }, + { + "associatedValues" : [ + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + } + ], + "name" : "coordinates" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "comprehensive" + }, + { + "associatedValues" : [ + + ], + "name" : "info" + } + ], + "emitStyle" : "const", + "name" : "ComplexResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "ComplexResult", + "tsFullPath" : "ComplexResult" + } + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_run", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "run", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + { + "methods" : [ + + ], + "name" : "SimpleStruct", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "count", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "flag", + "type" : { + "bool" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "rate", + "type" : { + "float" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "precise", + "type" : { + "double" : { + + } + } + } + ], + "swiftCallName" : "SimpleStruct" + }, + { + "methods" : [ + + ], + "name" : "Address", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "street", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "city", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "zipCode", + "type" : { + "int" : { + + } + } + } + ], + "swiftCallName" : "Address" + }, + { + "methods" : [ + + ], + "name" : "Person", + "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" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "Person" + }, + { + "methods" : [ + + ], + "name" : "ComplexStruct", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "id", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "title", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "active", + "type" : { + "bool" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "score", + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "tags", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "metadata", + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "ComplexStruct" + }, + { + "methods" : [ + + ], + "name" : "Point", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "x", + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "y", + "type" : { + "double" : { + + } + } + } + ], + "swiftCallName" : "Point" + } + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "benchmarkHelperNoop", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "benchmarkHelperNoopWithNumber", + "parameters" : [ + { + "name" : "n", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "benchmarkRunner", + "parameters" : [ + { + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "name" : "body", + "type" : { + "jsObject" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "types" : [ + + ] + } + ] + }, + "moduleName" : "Benchmarks" +} \ No newline at end of file diff --git a/Benchmarks/Sources/bridge-js.d.ts b/Benchmarks/Sources/bridge-js.d.ts index a9eb5d0bf..9f5137e1e 100644 --- a/Benchmarks/Sources/bridge-js.d.ts +++ b/Benchmarks/Sources/bridge-js.d.ts @@ -1,3 +1,3 @@ -declare function benchmarkHelperNoop(): void; -declare function benchmarkHelperNoopWithNumber(n: number): void; -declare function benchmarkRunner(name: string, body: (n: number) => void): void; +export function benchmarkHelperNoop(): void; +export function benchmarkHelperNoopWithNumber(n: number): void; +export function benchmarkRunner(name: string, body: (n: number) => void): void; diff --git a/Benchmarks/run.js b/Benchmarks/run.js index 2305373a5..5a1ae61e6 100644 --- a/Benchmarks/run.js +++ b/Benchmarks/run.js @@ -3,6 +3,7 @@ import { defaultNodeSetup } from "./.build/plugins/PackageToJS/outputs/Package/p import fs from 'fs'; import path from 'path'; import { parseArgs } from "util"; +import { APIResultValues as APIResult, ComplexResultValues as ComplexResult } from "./.build/plugins/PackageToJS/outputs/Package/bridge-js.js"; /** * Update progress bar on the current line @@ -16,9 +17,43 @@ 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}`); + } +} + +/** + * Create a name filter function from CLI argument + * - Supports substring match (default) + * - Supports /regex/flags syntax + * @param {string|undefined} arg + * @returns {(name: string) => boolean} + */ +function createNameFilter(arg) { + if (!arg) { + return () => true; + } + if (arg.startsWith('/') && arg.lastIndexOf('/') > 0) { + const lastSlash = arg.lastIndexOf('/'); + const pattern = arg.slice(1, lastSlash); + const flags = arg.slice(lastSlash + 1); + try { + const re = new RegExp(pattern, flags); + return (name) => re.test(name); + } catch (e) { + console.error('Invalid regular expression for --filter:', e.message); + process.exit(1); + } + } + return (name) => name.includes(arg); } /** @@ -236,37 +271,614 @@ 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) { +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(); + const duration = endTime - startTime; + if (!results[name]) { + results[name] = [] + } + results[name].push(duration) + } const { exports } = await instantiate({ ...options, - imports: { + getImports: () => ({ benchmarkHelperNoop: () => { }, benchmarkHelperNoopWithNumber: (n) => { }, - benchmarkRunner: (name, body) => { - const startTime = performance.now(); - body(); - const endTime = performance.now(); - const duration = endTime - startTime; - if (!results[name]) { - results[name] = [] - } - results[name].push(duration) - } - } + benchmarkRunner: benchmarkRunner + }) }); exports.run(); + + const enumRoundtrip = new exports.EnumRoundtrip(); + benchmarkRunner("EnumRoundtrip/takeEnum success", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.take({ tag: APIResult.Tag.Success, param0: "Hello, world" }) + } + }) + benchmarkRunner("EnumRoundtrip/takeEnum failure", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.take({ tag: APIResult.Tag.Failure, param0: 42 }) + } + }) + benchmarkRunner("EnumRoundtrip/takeEnum flag", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.take({ tag: APIResult.Tag.Flag, param0: true }) + } + }) + benchmarkRunner("EnumRoundtrip/takeEnum rate", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.take({ tag: APIResult.Tag.Rate, param0: 0.5 }) + } + }) + benchmarkRunner("EnumRoundtrip/takeEnum precise", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.take({ tag: APIResult.Tag.Precise, param0: 0.5 }) + } + }) + benchmarkRunner("EnumRoundtrip/takeEnum info", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.take({ tag: APIResult.Tag.Info }) + } + }) + benchmarkRunner("EnumRoundtrip/makeSuccess", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.makeSuccess() + } + }) + benchmarkRunner("EnumRoundtrip/makeFailure", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.makeFailure() + } + }) + benchmarkRunner("EnumRoundtrip/makeFlag", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.makeFlag() + } + }) + benchmarkRunner("EnumRoundtrip/makeRate", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.makeRate() + } + }) + benchmarkRunner("EnumRoundtrip/makePrecise", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.makePrecise() + } + }) + benchmarkRunner("EnumRoundtrip/makeInfo", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.makeInfo() + } + }) + + benchmarkRunner("EnumRoundtrip/roundtrip", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.roundtrip({ tag: APIResult.Tag.Success, param0: "Hello, world" }) + } + }) + + const complexResultRoundtrip = new exports.ComplexResultRoundtrip(); + + benchmarkRunner("ComplexResultRoundtrip/takeEnum success", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.take({ tag: ComplexResult.Tag.Success, param0: "Operation completed" }) + } + }) + benchmarkRunner("ComplexResultRoundtrip/takeEnum error", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.take({ tag: ComplexResult.Tag.Error, param0: "Network timeout", param1: 503 }) + } + }) + benchmarkRunner("ComplexResultRoundtrip/takeEnum location", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.take({ tag: ComplexResult.Tag.Location, param0: 37.7749, param1: -122.4194, param2: "San Francisco" }) + } + }) + benchmarkRunner("ComplexResultRoundtrip/takeEnum status", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.take({ tag: ComplexResult.Tag.Status, param0: true, param1: 200, param2: "OK" }) + } + }) + benchmarkRunner("ComplexResultRoundtrip/takeEnum coordinates", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.take({ tag: ComplexResult.Tag.Coordinates, param0: 10.5, param1: 20.3, param2: 30.7 }) + } + }) + benchmarkRunner("ComplexResultRoundtrip/takeEnum comprehensive", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.take({ + tag: ComplexResult.Tag.Comprehensive, + param0: true, param1: false, param2: 42, param3: 100, + param4: 3.14, param5: 2.718, param6: "Hello", param7: "World", param8: "Test" + }) + } + }) + benchmarkRunner("ComplexResultRoundtrip/takeEnum info", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.take({ tag: ComplexResult.Tag.Info }) + } + }) + + benchmarkRunner("ComplexResultRoundtrip/makeSuccess", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.makeSuccess() + } + }) + benchmarkRunner("ComplexResultRoundtrip/makeError", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.makeError() + } + }) + benchmarkRunner("ComplexResultRoundtrip/makeLocation", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.makeLocation() + } + }) + benchmarkRunner("ComplexResultRoundtrip/makeStatus", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.makeStatus() + } + }) + benchmarkRunner("ComplexResultRoundtrip/makeCoordinates", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.makeCoordinates() + } + }) + benchmarkRunner("ComplexResultRoundtrip/makeComprehensive", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.makeComprehensive() + } + }) + benchmarkRunner("ComplexResultRoundtrip/makeInfo", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.makeInfo() + } + }) + + benchmarkRunner("ComplexResultRoundtrip/roundtrip", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.roundtrip({ tag: ComplexResult.Tag.Success, param0: "Hello, world" }) + } + }) + + const stringRoundtrip = new exports.StringRoundtrip(); + benchmarkRunner("StringRoundtrip/takeString", () => { + for (let i = 0; i < iterations; i++) { + stringRoundtrip.take("Hello, world") + } + }) + benchmarkRunner("StringRoundtrip/makeString", () => { + for (let i = 0; i < iterations; i++) { + stringRoundtrip.make() + } + }) + + 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(); + + benchmarkRunner("StructRoundtrip/takeSimple", () => { + for (let i = 0; i < iterations; i++) { + structRoundtrip.takeSimple({ name: "Hello", count: 42, flag: true, rate: 0.5, precise: 3.14159 }) + } + }) + benchmarkRunner("StructRoundtrip/makeSimple", () => { + for (let i = 0; i < iterations; i++) { + structRoundtrip.makeSimple() + } + }) + benchmarkRunner("StructRoundtrip/roundtripSimple", () => { + for (let i = 0; i < iterations; i++) { + structRoundtrip.roundtripSimple({ name: "Hello", count: 42, flag: true, rate: 0.5, precise: 3.14159 }) + } + }) + + benchmarkRunner("StructRoundtrip/takeAddress", () => { + for (let i = 0; i < iterations; i++) { + structRoundtrip.takeAddress({ street: "123 Main St", city: "San Francisco", zipCode: 94102 }) + } + }) + benchmarkRunner("StructRoundtrip/makeAddress", () => { + for (let i = 0; i < iterations; i++) { + structRoundtrip.makeAddress() + } + }) + benchmarkRunner("StructRoundtrip/roundtripAddress", () => { + for (let i = 0; i < iterations; i++) { + structRoundtrip.roundtripAddress({ street: "123 Main St", city: "San Francisco", zipCode: 94102 }) + } + }) + + benchmarkRunner("StructRoundtrip/takePerson", () => { + for (let i = 0; i < iterations; i++) { + structRoundtrip.takePerson({ + name: "John Doe", + age: 30, + address: { street: "456 Oak Ave", city: "New York", zipCode: 10001 }, + email: "john@example.com" + }) + } + }) + benchmarkRunner("StructRoundtrip/makePerson", () => { + for (let i = 0; i < iterations; i++) { + structRoundtrip.makePerson() + } + }) + benchmarkRunner("StructRoundtrip/roundtripPerson", () => { + for (let i = 0; i < iterations; i++) { + structRoundtrip.roundtripPerson({ + name: "John Doe", + age: 30, + address: { street: "456 Oak Ave", city: "New York", zipCode: 10001 }, + email: "john@example.com" + }) + } + }) + + benchmarkRunner("StructRoundtrip/takeComplex", () => { + for (let i = 0; i < iterations; i++) { + structRoundtrip.takeComplex({ + id: 12345, + title: "Test Item", + active: true, + score: 98.6, + tags: "swift,wasm,benchmark", + metadata: "{\"version\":1}" + }) + } + }) + benchmarkRunner("StructRoundtrip/makeComplex", () => { + for (let i = 0; i < iterations; i++) { + structRoundtrip.makeComplex() + } + }) + benchmarkRunner("StructRoundtrip/roundtripComplex", () => { + for (let i = 0; i < iterations; i++) { + structRoundtrip.roundtripComplex({ + id: 12345, + title: "Test Item", + active: true, + score: 98.6, + tags: "swift,wasm,benchmark", + metadata: "{\"version\":1}" + }) + } + }) + + // Class vs Struct comparison tests + const classRoundtrip = new exports.ClassRoundtrip(); + + benchmarkRunner("ClassRoundtrip/takeSimpleClass", () => { + const simple = new exports.SimpleClass("Hello", 42, true, 0.5, 3.14159) + for (let i = 0; i < iterations; i++) { + classRoundtrip.takeSimpleClass(simple) + } + }) + benchmarkRunner("ClassRoundtrip/makeSimpleClass", () => { + for (let i = 0; i < iterations; i++) { + classRoundtrip.makeSimpleClass() + } + }) + benchmarkRunner("ClassRoundtrip/roundtripSimpleClass", () => { + const simple = new exports.SimpleClass("Hello", 42, true, 0.5, 3.14159) + for (let i = 0; i < iterations; i++) { + classRoundtrip.roundtripSimpleClass(simple) + } + }) + + benchmarkRunner("ClassRoundtrip/takeAddressClass", () => { + const address = new exports.AddressClass("123 Main St", "San Francisco", 94102) + for (let i = 0; i < iterations; i++) { + classRoundtrip.takeAddressClass(address) + } + }) + benchmarkRunner("ClassRoundtrip/makeAddressClass", () => { + for (let i = 0; i < iterations; i++) { + classRoundtrip.makeAddressClass() + } + }) + benchmarkRunner("ClassRoundtrip/roundtripAddressClass", () => { + const address = new exports.AddressClass("123 Main St", "San Francisco", 94102) + for (let i = 0; i < iterations; i++) { + 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) { +async function runUntilStable(results, options, width, nameFilter, filterArg, iterations) { const { minRuns = 5, maxRuns = 50, @@ -285,9 +897,14 @@ async function runUntilStable(results, options, width) { // Update progress with estimated completion updateProgress(runs, maxRuns, "Benchmark Progress:", width); - await singleRun(results); + await singleRun(results, nameFilter, iterations); runs++; + if (runs === 1 && Object.keys(results).length === 0) { + console.error(`\nNo benchmarks matched filter: ${filterArg}`); + process.exit(1); + } + // Check if we've reached minimum runs if (runs < minRuns) continue; @@ -343,12 +960,14 @@ 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) --min-runs=NUMBER Minimum runs for adaptive sampling (default: 5) --max-runs=NUMBER Maximum runs for adaptive sampling (default: 50) --target-cv=NUMBER Target coefficient of variation % (default: 5) + --filter=PATTERN Filter benchmarks by name (substring or /regex/flags) --help Show this help message `); } @@ -357,13 +976,15 @@ 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 }, adaptive: { type: 'boolean', default: false }, 'min-runs': { type: 'string', default: '5' }, 'max-runs': { type: 'string', default: '50' }, - 'target-cv': { type: 'string', default: '5' } + 'target-cv': { type: 'string', default: '5' }, + filter: { type: 'string' } } }); @@ -374,6 +995,14 @@ async function main() { const results = {}; const width = 30; + 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 @@ -388,7 +1017,7 @@ async function main() { console.log(`Results will be saved to: ${args.values.output}`); } - await runUntilStable(results, options, width); + await runUntilStable(results, options, width, nameFilter, filterArg, iterations); } else { // Fixed number of runs mode const runs = parseInt(args.values.runs, 10); @@ -410,7 +1039,12 @@ async function main() { console.log("\nOverall Progress:"); for (let i = 0; i < runs; i++) { updateProgress(i, runs, "Benchmark Runs:", width); - await singleRun(results); + await singleRun(results, nameFilter, iterations); + if (i === 0 && Object.keys(results).length === 0) { + process.stdout.write("\n"); + console.error(`No benchmarks matched filter: ${filterArg}`); + process.exit(1); + } } updateProgress(runs, runs, "Benchmark Runs:", width); console.log("\n"); diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 666b62d24..d984555e6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,41 +18,24 @@ Thank you for considering contributing to JavaScriptKit! We welcome contribution cd JavaScriptKit ``` -2. Install **OSS** Swift toolchain (not the one from Xcode): -
- For macOS users - - ```bash - ( - SWIFT_TOOLCHAIN_CHANNEL=swift-6.0.2-release; - SWIFT_TOOLCHAIN_TAG="swift-6.0.2-RELEASE"; - SWIFT_SDK_TAG="swift-wasm-6.0.2-RELEASE"; - SWIFT_SDK_CHECKSUM="6ffedb055cb9956395d9f435d03d53ebe9f6a8d45106b979d1b7f53358e1dcb4"; - pkg="$(mktemp -d)/InstallMe.pkg"; set -ex; - curl -o "$pkg" "https://download.swift.org/$SWIFT_TOOLCHAIN_CHANNEL/xcode/$SWIFT_TOOLCHAIN_TAG/$SWIFT_TOOLCHAIN_TAG-osx.pkg"; - installer -pkg "$pkg" -target CurrentUserHomeDirectory; - export TOOLCHAINS="$(plutil -extract CFBundleIdentifier raw ~/Library/Developer/Toolchains/$SWIFT_TOOLCHAIN_TAG.xctoolchain/Info.plist)"; - swift sdk install "https://github.com/swiftwasm/swift/releases/download/$SWIFT_SDK_TAG/$SWIFT_SDK_TAG-wasm32-unknown-wasi.artifactbundle.zip" --checksum "$SWIFT_SDK_CHECKSUM"; - ) - ``` - -
- -
- For Linux users - Install Swift 6.0.2 by following the instructions on the official Swift website. - +2. Install **OSS** Swift toolchain via `swiftly` +3. Install Swift SDK for Wasm corresponding to the Swift version: ```bash ( - SWIFT_SDK_TAG="swift-wasm-6.0.2-RELEASE"; - SWIFT_SDK_CHECKSUM="6ffedb055cb9956395d9f435d03d53ebe9f6a8d45106b979d1b7f53358e1dcb4"; - swift sdk install "https://github.com/swiftwasm/swift/releases/download/$SWIFT_SDK_TAG/$SWIFT_SDK_TAG-wasm32-unknown-wasi.artifactbundle.zip" --checksum "$SWIFT_SDK_CHECKSUM"; + set -eo pipefail; \ + V="$(swiftc --version | head -n1)"; \ + TAG="$(curl -sL "https://raw.githubusercontent.com/swiftwasm/swift-sdk-index/refs/heads/main/v1/tag-by-version.json" | jq -e -r --arg v "$V" '.[$v] | .[-1]')"; \ + curl -sL "https://raw.githubusercontent.com/swiftwasm/swift-sdk-index/refs/heads/main/v1/builds/$TAG.json" | \ + jq -r '.["swift-sdks"]["wasm32-unknown-wasip1"] | "swift sdk install \"\(.url)\" --checksum \"\(.checksum)\""' | sh -x + ); + export SWIFT_SDK_ID=$( + V="$(swiftc --version | head -n1)"; \ + TAG="$(curl -sL "https://raw.githubusercontent.com/swiftwasm/swift-sdk-index/refs/heads/main/v1/tag-by-version.json" | jq -e -r --arg v "$V" '.[$v] | .[-1]')"; \ + curl -sL "https://raw.githubusercontent.com/swiftwasm/swift-sdk-index/refs/heads/main/v1/builds/$TAG.json" | \ + jq -r '.["swift-sdks"]["wasm32-unknown-wasip1"]["id"]' ) ``` - -
- -3. Install dependencies: +4. Install dependencies: ```bash make bootstrap ``` @@ -62,7 +45,7 @@ Thank you for considering contributing to JavaScriptKit! We welcome contribution Unit tests running on WebAssembly: ```bash -make unittest SWIFT_SDK_ID=wasm32-unknown-wasi +make unittest ``` Tests for `PackageToJS` plugin: @@ -77,6 +60,12 @@ Tests for `BridgeJS` plugin: swift test --package-path ./Plugins/BridgeJS ``` +This runs both the TS2Swift Vitest suite (TypeScript `.d.ts` -> Swift macro output) and the Swift codegen/link tests. For fast iteration on the ts2swift tool only, run Vitest directly: + +```bash +cd Plugins/BridgeJS/Sources/TS2Swift/JavaScript && npm test +``` + To update snapshot test files when expected output changes: ```bash @@ -112,5 +101,9 @@ Run this script when you've made changes to: These changes require updating the pre-generated Swift bindings committed to the repository. +**Adding new BridgeJS intrinsics:** + +If you add new `@_extern(wasm, module: "bjs")` functions to [`BridgeJSIntrinsics.swift`](Sources/JavaScriptKit/BridgeJSIntrinsics.swift), also add corresponding stub entries to [`Plugins/PackageToJS/Templates/instantiate.js`](Plugins/PackageToJS/Templates/instantiate.js) in the `importObject["bjs"]` object. This allows packages without BridgeJS-generated code to instantiate successfully. + ## Support If you have any questions or need assistance, feel free to reach out via [GitHub Issues](https://github.com/swiftwasm/JavaScriptKit/issues) or [Discord](https://discord.gg/ashJW8T8yp). diff --git a/Examples/ActorOnWebWorker/Sources/MyApp.swift b/Examples/ActorOnWebWorker/Sources/MyApp.swift index 9b38fa30c..c5f452d81 100644 --- a/Examples/ActorOnWebWorker/Sources/MyApp.swift +++ b/Examples/ActorOnWebWorker/Sources/MyApp.swift @@ -30,7 +30,7 @@ actor SearchService { // Utility function for fetch func fetch(_ url: String) -> JSPromise { - let jsFetch = JSObject.global.fetch.function! + let jsFetch = JSObject.global.fetch.object! return JSPromise(jsFetch(url).object!)! } @@ -117,7 +117,7 @@ struct SearchResult { @MainActor final class App { private let document = JSObject.global.document - private let alert = JSObject.global.alert.function! + private let alert = JSObject.global.alert.object! // UI elements private let container: JSValue 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/Sources/main.swift b/Examples/Basic/Sources/main.swift index 7ea9231e1..af0a12510 100644 --- a/Examples/Basic/Sources/main.swift +++ b/Examples/Basic/Sources/main.swift @@ -1,7 +1,7 @@ import JavaScriptEventLoop import JavaScriptKit -let alert = JSObject.global.alert.function! +let alert = JSObject.global.alert.object! let document = JSObject.global.document let divElement = document.createElement("div") @@ -19,7 +19,7 @@ buttonElement.onclick = .object( _ = document.body.appendChild(buttonElement) -private let jsFetch = JSObject.global.fetch.function! +private let jsFetch = JSObject.global.fetch.object! func fetch(_ url: String) -> JSPromise { JSPromise(jsFetch(url).object!)! } diff --git a/Examples/Basic/build.sh b/Examples/Basic/build.sh index e6e67d93c..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_wasi:-${SWIFT_SDK_ID:-wasm32-unknown-wasi}}" -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/Embedded/Package.swift b/Examples/Embedded/Package.swift index 5ae19adc6..42702394a 100644 --- a/Examples/Embedded/Package.swift +++ b/Examples/Embedded/Package.swift @@ -5,32 +5,17 @@ import PackageDescription let package = Package( name: "Embedded", dependencies: [ - .package(name: "JavaScriptKit", path: "../../"), - .package(url: "https://github.com/swiftwasm/swift-dlmalloc", branch: "0.1.0"), + .package(name: "JavaScriptKit", path: "../../") ], targets: [ .executableTarget( name: "EmbeddedApp", dependencies: [ - "JavaScriptKit", - .product(name: "dlmalloc", package: "swift-dlmalloc"), + "JavaScriptKit" ], - cSettings: [.unsafeFlags(["-fdeclspec"])], swiftSettings: [ - .enableExperimentalFeature("Embedded"), - .enableExperimentalFeature("Extern"), - .unsafeFlags([ - "-Xfrontend", "-gnone", - "-Xfrontend", "-disable-stack-protector", - ]), + .enableExperimentalFeature("Extern") ], - linkerSettings: [ - .unsafeFlags([ - "-Xclang-linker", "-nostdlib", - "-Xlinker", "--no-entry", - "-Xlinker", "--export-if-defined=__main_argc_argv", - ]) - ] ) ], swiftLanguageModes: [.v5] diff --git a/Examples/Embedded/Sources/EmbeddedApp/_thingsThatShouldNotBeNeeded.swift b/Examples/Embedded/Sources/EmbeddedApp/_thingsThatShouldNotBeNeeded.swift deleted file mode 100644 index 8f45ccee9..000000000 --- a/Examples/Embedded/Sources/EmbeddedApp/_thingsThatShouldNotBeNeeded.swift +++ /dev/null @@ -1,36 +0,0 @@ -import JavaScriptKit - -// NOTE: it seems the embedded tree shaker gets rid of these exports if they are not used somewhere -func _i_need_to_be_here_for_wasm_exports_to_work() { - _ = _swjs_library_features - _ = _swjs_call_host_function - _ = _swjs_free_host_function -} - -// TODO: why do I need this? and surely this is not ideal... figure this out, or at least have this come from a C lib -@_cdecl("strlen") -func strlen(_ s: UnsafePointer) -> Int { - var p = s - while p.pointee != 0 { - p += 1 - } - return p - s -} - -enum LCG { - static var x: UInt8 = 0 - static let a: UInt8 = 0x05 - static let c: UInt8 = 0x0b - - static func next() -> UInt8 { - x = a &* x &+ c - return x - } -} - -@_cdecl("arc4random_buf") -public func arc4random_buf(_ buffer: UnsafeMutableRawPointer, _ size: Int) { - for i in 0..( unsafelyWrapping: encode(this: textEncoder, textInputElement.value).object! ) diff --git a/Examples/Embedded/build.sh b/Examples/Embedded/build.sh index c54193f17..d756d8d1e 100755 --- a/Examples/Embedded/build.sh +++ b/Examples/Embedded/build.sh @@ -1,6 +1,5 @@ #!/bin/bash set -euxo pipefail package_dir="$(cd "$(dirname "$0")" && pwd)" -JAVASCRIPTKIT_EXPERIMENTAL_EMBEDDED_WASM=true \ - swift package --package-path "$package_dir" \ - -c release --triple wasm32-unknown-none-wasm js +swift package --package-path "$package_dir" \ + --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1}}-embedded" js -c release diff --git a/Examples/ExportSwift/README.md b/Examples/ExportSwift/README.md index 57d419295..39c66f0a6 100644 --- a/Examples/ExportSwift/README.md +++ b/Examples/ExportSwift/README.md @@ -5,7 +5,7 @@ This example demonstrates how to export Swift functions to JavaScript. 1. Build the project: ```sh - env JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --swift-sdk $SWIFT_SDK_ID js --use-cdn + swift package --swift-sdk $SWIFT_SDK_ID js --use-cdn ``` 2. Serve the files: diff --git a/Examples/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/NodeJS/.gitignore b/Examples/NodeJS/.gitignore new file mode 100644 index 000000000..0023a5340 --- /dev/null +++ b/Examples/NodeJS/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/Examples/NodeJS/Package.swift b/Examples/NodeJS/Package.swift new file mode 100644 index 000000000..83a84fc8e --- /dev/null +++ b/Examples/NodeJS/Package.swift @@ -0,0 +1,15 @@ +// swift-tools-version: 6.2 + +import PackageDescription + +let package = Package( + name: "NodeJS", + dependencies: [.package(name: "JavaScriptKit", path: "../../")], + targets: [ + .executableTarget( + name: "NodeJS", + dependencies: ["JavaScriptKit"] + ) + ], + swiftLanguageModes: [.v6] +) diff --git a/Examples/NodeJS/README.md b/Examples/NodeJS/README.md new file mode 100644 index 000000000..2b4e03218 --- /dev/null +++ b/Examples/NodeJS/README.md @@ -0,0 +1,9 @@ +# Node.js example + +This example demonstrates how to use JavaScriptKit with Node.js. It shows how to export Swift functions to JavaScript and run them in a Node.js environment. + +```sh +$ swift package --swift-sdk $SWIFT_SDK_ID js +$ node main.mjs +``` + diff --git a/Examples/NodeJS/Sources/NodeJS/NodeJS.swift b/Examples/NodeJS/Sources/NodeJS/NodeJS.swift new file mode 100644 index 000000000..deebc1bd8 --- /dev/null +++ b/Examples/NodeJS/Sources/NodeJS/NodeJS.swift @@ -0,0 +1,12 @@ +import JavaScriptKit + +@main +struct NodeJS { + static func main() { + JSObject.global["greet"] = + JSClosure { args in + let nameString = args[0].string! + return .string("Hello, \(nameString) from NodeJS!") + }.jsValue + } +} diff --git a/Examples/NodeJS/main.mjs b/Examples/NodeJS/main.mjs new file mode 100644 index 000000000..5aca7d0a7 --- /dev/null +++ b/Examples/NodeJS/main.mjs @@ -0,0 +1,18 @@ +// @ts-check + +import { instantiate } from "./.build/plugins/PackageToJS/outputs/Package/instantiate.js" +import { defaultNodeSetup } from "./.build/plugins/PackageToJS/outputs/Package/platforms/node.js" + +async function main() { + // Create a default Node.js option object + const options = await defaultNodeSetup(); + // Instantiate the Swift code, executing + // NodeJS.main() in NodeJS.swift + await instantiate(options); + + // Call the greet function set by NodeJS.swift + const greet = globalThis.greet; + console.log(greet("World")); +} + +main() 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/Sources/JavaScript/app.js b/Examples/PlayBridgeJS/Sources/JavaScript/app.js index 9e1d39e27..5580c802d 100644 --- a/Examples/PlayBridgeJS/Sources/JavaScript/app.js +++ b/Examples/PlayBridgeJS/Sources/JavaScript/app.js @@ -3,9 +3,14 @@ import { EditorSystem } from './editor.js'; import ts from 'typescript'; import { TypeProcessor } from './processor.js'; import { CodeShareManager } from './code-share.js'; +import { + createSystem, + createDefaultMapFromCDN, + createVirtualCompilerHost +} from '@typescript/vfs'; /** - * @typedef {import('../../.build/plugins/PackageToJS/outputs/Package/bridge-js.js').PlayBridgeJS} PlayBridgeJS + * @typedef {import('../../Bundle/bridge-js.js').PlayBridgeJS} PlayBridgeJS */ /** @@ -38,6 +43,14 @@ export class BridgeJSPlayground { this.copyButton = /** @type {HTMLButtonElement} */ (document.getElementById('copyButton')); /** @type {HTMLButtonElement} */ this.closeShareDialogButton = /** @type {HTMLButtonElement} */ (document.getElementById('closeShareDialog')); + + // Progress UI elements + /** @type {HTMLDivElement | null} */ + this.progressBar = /** @type {HTMLDivElement} */ (document.getElementById('progressBar')); + /** @type {HTMLDivElement | null} */ + this.progressFill = /** @type {HTMLDivElement} */ (document.getElementById('progressFill')); + /** @type {HTMLDivElement | null} */ + this.progressLabel = /** @type {HTMLDivElement} */ (document.getElementById('progressLabel')); } /** @@ -50,16 +63,20 @@ export class BridgeJSPlayground { } try { + this.showProgress('Starting…', 5); // Initialize editor system await this.editorSystem.init(); + this.setProgress('Editor ready', 30); // Initialize BridgeJS await this.initializeBridgeJS(); + this.setProgress('BridgeJS ready', 70); // Set up event listeners this.setupEventListeners(); // Check for shared code in URL + this.setProgress('Checking shared code…', 80); const sharedCode = await CodeShareManager.extractCodeFromUrl(); if (sharedCode) { this.editorSystem.setInputs(sharedCode); @@ -67,12 +84,15 @@ export class BridgeJSPlayground { // Load sample code this.editorSystem.setInputs(sampleCode); } - + this.setProgress('Finalizing…', 95); this.isInitialized = true; console.log('BridgeJS Playground initialized successfully'); + this.setProgress('Ready', 100); + setTimeout(() => this.hideProgress(), 400); } catch (error) { console.error('Failed to initialize BridgeJS Playground:', error); this.showError('Failed to initialize application: ' + error.message); + this.hideProgress(); } } @@ -80,14 +100,16 @@ export class BridgeJSPlayground { async initializeBridgeJS() { try { // Import the BridgeJS module - const { init } = await import("../../.build/plugins/PackageToJS/outputs/Package/index.js"); + this.setProgress('Loading BridgeJS…', 50); + const { init } = await import("../../Bundle/index.js"); + const virtualHost = await this.createTS2SwiftFactory(); + this.setProgress('Preparing TypeScript host…', 60); const { exports } = await init({ - getImports: () => { - return { - createTS2Skeleton: this.createTS2Skeleton - }; - } + getImports: () => ({ + createTS2Swift: () => this.createTS2Swift(virtualHost) + }) }); + this.setProgress('Creating runtime…', 65); this.playBridgeJS = new exports.PlayBridgeJS(); console.log('BridgeJS initialized successfully'); } catch (error) { @@ -171,32 +193,44 @@ export class BridgeJSPlayground { }); } - createTS2Skeleton() { + async createTS2SwiftFactory() { + const createVirtualHost = async () => { + const fsMap = await createDefaultMapFromCDN( + { target: ts.ScriptTarget.ES2015 }, + ts.version, + true, + ts + ); + + const system = createSystem(fsMap); + + const compilerOptions = { + target: ts.ScriptTarget.ES2015, + lib: ["es2015", "dom"], + }; + + return createVirtualCompilerHost(system, compilerOptions, ts); + } + return await createVirtualHost(); + } + + /** + * @param {ReturnType} virtualHost + */ + createTS2Swift(virtualHost) { return { + /** + * @param {string} dtsCode + * @returns {string} + */ convert: (dtsCode) => { - const virtualFilePath = "bridge-js.d.ts" - const virtualHost = { - fileExists: fileName => fileName === virtualFilePath, - readFile: fileName => dtsCode, - getSourceFile: (fileName, languageVersion) => { - const sourceText = dtsCode; - if (sourceText === undefined) return undefined; - return ts.createSourceFile(fileName, sourceText, languageVersion); - }, - getDefaultLibFileName: options => "lib.d.ts", - writeFile: (fileName, data) => { - console.log(`[emit] ${fileName}:\n${data}`); - }, - getCurrentDirectory: () => "", - getDirectories: () => [], - getCanonicalFileName: fileName => fileName, - getNewLine: () => "\n", - useCaseSensitiveFileNames: () => true - } // Create TypeScript program from d.ts content + const virtualFilePath = "bridge-js.d.ts" + const sourceFile = ts.createSourceFile(virtualFilePath, dtsCode, ts.ScriptTarget.ES2015); + virtualHost.updateFile(sourceFile); const tsProgram = ts.createProgram({ rootNames: [virtualFilePath], - host: virtualHost, + host: virtualHost.compilerHost, options: { noEmit: true, declaration: true, @@ -216,9 +250,9 @@ export class BridgeJSPlayground { // Process the TypeScript definitions to generate skeleton const processor = new TypeProcessor(tsProgram.getTypeChecker(), diagnosticEngine); - const skeleton = processor.processTypeDeclarations(tsProgram, virtualFilePath); + const { content } = processor.processTypeDeclarations(tsProgram, virtualFilePath); - return JSON.stringify(skeleton); + return content; } } } @@ -234,19 +268,38 @@ export class BridgeJSPlayground { try { this.hideError(); + this.editorSystem.clearDiagnostics(); const inputs = this.editorSystem.getInputs(); const swiftCode = inputs.swift; const dtsCode = inputs.dts; // Process the code and get PlayBridgeJSOutput - const result = this.playBridgeJS.update(swiftCode, dtsCode); - - // Update outputs using the PlayBridgeJSOutput object - this.editorSystem.updateOutputs(result); - - console.log('Code generated successfully'); + const result = this.playBridgeJS.updateDetailed(swiftCode, dtsCode); + + const diagnostics = result.diagnostics; + if (diagnostics && diagnostics.length > 0) { + const mapped = diagnostics.map(d => ({ + file: d.file, + startLineNumber: d.startLine, + startColumn: d.startColumn, + endLineNumber: d.endLine, + endColumn: d.endColumn, + message: d.message + })); + this.editorSystem.showDiagnostics(mapped); + return; + } + const output = result.output; + if (output) { + // Update outputs using the PlayBridgeJSOutput object + this.editorSystem.updateOutputs(output); + this.hideError(); + console.log('Code generated successfully'); + } else { + this.showError('No output produced.'); + } } catch (error) { console.error('Error generating code:', error); this.showError('Error generating code: ' + error.message); @@ -268,4 +321,42 @@ export class BridgeJSPlayground { hideError() { this.errorDisplay.classList.remove('show'); } -} \ No newline at end of file + + /** + * Shows progress bar. + * @param {string} label + * @param {number} percent + */ + showProgress(label, percent) { + if (this.progressBar) { + this.progressBar.classList.add('show'); + this.progressBar.classList.remove('hidden'); + } + this.setProgress(label, percent); + } + + /** + * Updates progress label and percentage. + * @param {string} label + * @param {number} percent + */ + setProgress(label, percent) { + if (this.progressLabel) { + this.progressLabel.textContent = label; + } + if (this.progressFill) { + const clamped = Math.max(0, Math.min(100, Number(percent) || 0)); + this.progressFill.style.width = clamped + '%'; + } + } + + /** + * Hides progress bar. + */ + hideProgress() { + if (this.progressBar) { + this.progressBar.classList.remove('show'); + this.progressBar.classList.add('hidden'); + } + } +} diff --git a/Examples/PlayBridgeJS/Sources/JavaScript/editor.js b/Examples/PlayBridgeJS/Sources/JavaScript/editor.js index dabe7dc5b..97e78a1f8 100644 --- a/Examples/PlayBridgeJS/Sources/JavaScript/editor.js +++ b/Examples/PlayBridgeJS/Sources/JavaScript/editor.js @@ -38,20 +38,20 @@ export class EditorSystem { modelUri: 'Playground.d.ts' }, { - key: 'import-glue', - id: 'importGlueOutput', + key: 'swift-import-macros', + id: 'swiftImportMacrosOutput', language: 'swift', - placeholder: '// Import Swift Glue will appear here...', + placeholder: '// Import Swift Macros will appear here...', readOnly: true, - modelUri: 'ImportTS.swift' + modelUri: 'Playground.Macros.swift' }, { - key: 'export-glue', - id: 'exportGlueOutput', + key: 'swift-glue', + id: 'swiftGlueOutput', language: 'swift', - placeholder: '// Export Swift Glue will appear here...', + placeholder: '// Swift Glue will appear here...', readOnly: true, - modelUri: 'ExportTS.swift' + modelUri: 'BridgeJS.swift' }, { key: 'js-generated', @@ -97,7 +97,7 @@ export class EditorSystem { scrollbar: { vertical: 'visible', horizontal: 'visible' }, fixedOverflowWidgets: true, renderWhitespace: 'none', - wordWrap: 'on' + wordWrap: 'off' }; // Create all editors from config @@ -206,10 +206,10 @@ export class EditorSystem { updateOutputs(result) { const outputMap = { - 'import-glue': () => result.importSwiftGlue(), - 'export-glue': () => result.exportSwiftGlue(), - 'js-generated': () => result.outputJs(), - 'dts-generated': () => result.outputDts() + 'swift-glue': () => result.swiftGlue, + 'swift-import-macros': () => result.importSwiftMacroDecls, + 'js-generated': () => result.outputJs, + 'dts-generated': () => result.outputDts }; Object.entries(outputMap).forEach(([key, getContent]) => { @@ -230,6 +230,63 @@ export class EditorSystem { }); } + clearDiagnostics() { + // Remove all diagnostics owned by the playground. + this.editors.forEach(editor => { + const model = editor.getModel(); + if (!model || typeof monaco === 'undefined') return; + monaco.editor.setModelMarkers(model, 'bridgejs', []); + }); + } + + /** + * @param {{file: string, startLineNumber: number, startColumn: number, endLineNumber?: number, endColumn?: number, message: string}[]} diagnostics + */ + showDiagnostics(diagnostics) { + if (typeof monaco === 'undefined') return; + + // Group diagnostics per model so we can set markers in batches. + const markersByModel = new Map(); + + diagnostics.forEach(diag => { + const model = this.findModelForFile(diag.file); + if (!model) return; + + const markers = markersByModel.get(model) ?? []; + const lineLength = model.getLineMaxColumn(diag.startLineNumber); + const endLine = diag.endLineNumber ?? diag.startLineNumber; + const endColumn = Math.min(lineLength, diag.endColumn ?? diag.startColumn + 1); + + markers.push({ + severity: monaco.MarkerSeverity.Error, + message: diag.message, + startLineNumber: diag.startLineNumber, + startColumn: diag.startColumn, + endLineNumber: endLine, + endColumn + }); + + markersByModel.set(model, markers); + }); + + markersByModel.forEach((markers, model) => { + monaco.editor.setModelMarkers(model, 'bridgejs', markers); + }); + } + + findModelForFile(fileName) { + const normalized = fileName.startsWith('/') ? fileName.slice(1) : fileName; + for (const editor of this.editors.values()) { + const model = editor.getModel(); + if (!model) continue; + const uriPath = model.uri.path.startsWith('/') ? model.uri.path.slice(1) : model.uri.path; + if (uriPath === normalized || uriPath.endsWith('/' + normalized)) { + return model; + } + } + return null; + } + // Utility methods getConfigByKey(key) { return [...this.config.input, ...this.config.output].find(c => c.key === key); @@ -238,4 +295,4 @@ export class EditorSystem { getActiveTabs() { return this.activeTabs; } -} \ No newline at end of file +} diff --git a/Examples/PlayBridgeJS/Sources/JavaScript/processor.js b/Examples/PlayBridgeJS/Sources/JavaScript/processor.js index 61c833925..646254cd4 120000 --- a/Examples/PlayBridgeJS/Sources/JavaScript/processor.js +++ b/Examples/PlayBridgeJS/Sources/JavaScript/processor.js @@ -1 +1 @@ -../../../../Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/src/processor.js \ No newline at end of file +../../../../Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/processor.js \ No newline at end of file diff --git a/Examples/PlayBridgeJS/Sources/JavaScript/styles.css b/Examples/PlayBridgeJS/Sources/JavaScript/styles.css index 1a8414e2f..f8eafbec9 100644 --- a/Examples/PlayBridgeJS/Sources/JavaScript/styles.css +++ b/Examples/PlayBridgeJS/Sources/JavaScript/styles.css @@ -49,13 +49,12 @@ body { background-color: var(--color-fill); color: var(--color-text); font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif; - height: 100vh; - overflow: hidden; + min-height: 100vh; line-height: 1.5; } .container { - height: 100vh; + min-height: 100vh; padding: 24px; display: flex; flex-direction: column; @@ -221,6 +220,47 @@ body { word-break: break-word; } +/* Progress bar */ +.progress { + margin: 16px auto 0 auto; + max-width: 640px; + opacity: 0; + visibility: hidden; + transition: opacity 0.2s ease; +} + +.progress.show { + opacity: 1; + visibility: visible; +} + +.progress.hidden { + opacity: 0; + visibility: hidden; +} + +.progress-track { + height: 8px; + background-color: var(--color-fill-tertiary); + border: 1px solid var(--color-border); + border-radius: 999px; + overflow: hidden; +} + +.progress-fill { + height: 100%; + width: 0%; + background-color: var(--color-figure-blue); + transition: width 0.2s ease; +} + +.progress-label { + margin-top: 8px; + text-align: center; + font-size: 12px; + color: var(--color-secondary-label); +} + .main-content { flex: 1; display: grid; @@ -266,6 +306,10 @@ body { margin: 0; background-color: var(--color-fill-secondary); border-bottom: 1px solid var(--color-border); + overflow-x: auto; + overflow-y: hidden; + scrollbar-gutter: stable; + -webkit-overflow-scrolling: touch; } .tab-button { @@ -279,6 +323,8 @@ body { transition: all 0.2s ease; position: relative; border-bottom: 2px solid transparent; + flex: 0 0 auto; + white-space: nowrap; } .tab-button:hover { @@ -342,15 +388,26 @@ body { } @media (max-width: 768px) { + body { + overflow: auto; + } + .main-content { grid-template-columns: 1fr; gap: 16px; + flex: none; } .container { + height: auto; + min-height: 100vh; padding: 12px; } + .editor-container { + min-height: 300px; + } + .header h1 { font-size: 24px; } @@ -360,12 +417,10 @@ body { } .tab-group { - flex-wrap: wrap; + scroll-padding-inline: 12px; } .tab-button { - flex: 1; - min-width: 0; text-align: center; } @@ -396,4 +451,4 @@ body { .share-url-input { font-size: 12px; } -} \ No newline at end of file +} diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/BridgeJSUtilities b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/BridgeJSUtilities new file mode 120000 index 000000000..a43f43e2c --- /dev/null +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/BridgeJSUtilities @@ -0,0 +1 @@ +../../../../Plugins/BridgeJS/Sources/BridgeJSUtilities \ No newline at end of file diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.ExportSwift.swift b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.ExportSwift.swift deleted file mode 100644 index 3936b254b..000000000 --- a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.ExportSwift.swift +++ /dev/null @@ -1,131 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -@_expose(wasm, "bjs_PlayBridgeJS_init") -@_cdecl("bjs_PlayBridgeJS_init") -public func _bjs_PlayBridgeJS_init() -> UnsafeMutableRawPointer { - #if arch(wasm32) - let ret = PlayBridgeJS() - return Unmanaged.passRetained(ret).toOpaque() - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_PlayBridgeJS_update") -@_cdecl("bjs_PlayBridgeJS_update") -public func _bjs_PlayBridgeJS_update(_self: UnsafeMutableRawPointer, swiftSourceBytes: Int32, swiftSourceLen: Int32, dtsSourceBytes: Int32, dtsSourceLen: Int32) -> UnsafeMutableRawPointer { - #if arch(wasm32) - do { - let swiftSource = String(unsafeUninitializedCapacity: Int(swiftSourceLen)) { b in - _swift_js_init_memory(swiftSourceBytes, b.baseAddress.unsafelyUnwrapped) - return Int(swiftSourceLen) - } - let dtsSource = String(unsafeUninitializedCapacity: Int(dtsSourceLen)) { b in - _swift_js_init_memory(dtsSourceBytes, b.baseAddress.unsafelyUnwrapped) - return Int(dtsSourceLen) - } - let ret = try Unmanaged.fromOpaque(_self).takeUnretainedValue().update(swiftSource: swiftSource, dtsSource: dtsSource) - return Unmanaged.passRetained(ret).toOpaque() - } catch let error { - if let error = error.thrownValue.object { - withExtendedLifetime(error) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } else { - let jsError = JSError(message: String(describing: error)) - withExtendedLifetime(jsError.jsObject) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } - return UnsafeMutableRawPointer(bitPattern: -1).unsafelyUnwrapped - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_PlayBridgeJS_deinit") -@_cdecl("bjs_PlayBridgeJS_deinit") -public func _bjs_PlayBridgeJS_deinit(pointer: UnsafeMutableRawPointer) { - Unmanaged.fromOpaque(pointer).release() -} - -extension PlayBridgeJS: ConvertibleToJSValue { - var jsValue: JSValue { - @_extern(wasm, module: "PlayBridgeJS", name: "bjs_PlayBridgeJS_wrap") - func _bjs_PlayBridgeJS_wrap(_: UnsafeMutableRawPointer) -> Int32 - return .object(JSObject(id: UInt32(bitPattern: _bjs_PlayBridgeJS_wrap(Unmanaged.passRetained(self).toOpaque())))) - } -} - -@_expose(wasm, "bjs_PlayBridgeJSOutput_outputJs") -@_cdecl("bjs_PlayBridgeJSOutput_outputJs") -public func _bjs_PlayBridgeJSOutput_outputJs(_self: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().outputJs() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_PlayBridgeJSOutput_outputDts") -@_cdecl("bjs_PlayBridgeJSOutput_outputDts") -public func _bjs_PlayBridgeJSOutput_outputDts(_self: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().outputDts() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_PlayBridgeJSOutput_importSwiftGlue") -@_cdecl("bjs_PlayBridgeJSOutput_importSwiftGlue") -public func _bjs_PlayBridgeJSOutput_importSwiftGlue(_self: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().importSwiftGlue() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_PlayBridgeJSOutput_exportSwiftGlue") -@_cdecl("bjs_PlayBridgeJSOutput_exportSwiftGlue") -public func _bjs_PlayBridgeJSOutput_exportSwiftGlue(_self: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().exportSwiftGlue() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_PlayBridgeJSOutput_deinit") -@_cdecl("bjs_PlayBridgeJSOutput_deinit") -public func _bjs_PlayBridgeJSOutput_deinit(pointer: UnsafeMutableRawPointer) { - Unmanaged.fromOpaque(pointer).release() -} - -extension PlayBridgeJSOutput: ConvertibleToJSValue { - var jsValue: JSValue { - @_extern(wasm, module: "PlayBridgeJS", name: "bjs_PlayBridgeJSOutput_wrap") - func _bjs_PlayBridgeJSOutput_wrap(_: UnsafeMutableRawPointer) -> Int32 - return .object(JSObject(id: UInt32(bitPattern: _bjs_PlayBridgeJSOutput_wrap(Unmanaged.passRetained(self).toOpaque())))) - } -} \ No newline at end of file diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.ImportTS.swift b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.ImportTS.swift deleted file mode 100644 index 5d82db08b..000000000 --- a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.ImportTS.swift +++ /dev/null @@ -1,59 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -func createTS2Skeleton() throws(JSException) -> TS2Skeleton { - #if arch(wasm32) - @_extern(wasm, module: "PlayBridgeJS", name: "bjs_createTS2Skeleton") - func bjs_createTS2Skeleton() -> Int32 - #else - func bjs_createTS2Skeleton() -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_createTS2Skeleton() - if let error = _swift_js_take_exception() { - throw error - } - return TS2Skeleton(takingThis: ret) -} - -struct TS2Skeleton { - let this: JSObject - - init(this: JSObject) { - self.this = this - } - - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) - } - - func convert(_ ts: String) throws(JSException) -> String { - #if arch(wasm32) - @_extern(wasm, module: "PlayBridgeJS", name: "bjs_TS2Skeleton_convert") - func bjs_TS2Skeleton_convert(_ self: Int32, _ ts: Int32) -> Int32 - #else - func bjs_TS2Skeleton_convert(_ self: Int32, _ ts: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - var ts = ts - let tsId = ts.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_TS2Skeleton_convert(Int32(bitPattern: self.this.id), tsId) - if let error = _swift_js_take_exception() { - throw error - } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } - } - -} \ No newline at end of file diff --git a/Benchmarks/Sources/Generated/BridgeJS.ExportSwift.swift b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.Macros.swift similarity index 54% rename from Benchmarks/Sources/Generated/BridgeJS.ExportSwift.swift rename to Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.Macros.swift index ee86def78..4a87a6d38 100644 --- a/Benchmarks/Sources/Generated/BridgeJS.ExportSwift.swift +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.Macros.swift @@ -6,12 +6,8 @@ @_spi(BridgeJS) import JavaScriptKit -@_expose(wasm, "bjs_run") -@_cdecl("bjs_run") -public func _bjs_run() -> Void { - #if arch(wasm32) - run() - #else - fatalError("Only available on WebAssembly") - #endif -} \ No newline at end of file +@JSFunction func createTS2Swift() throws(JSException) -> TS2Swift + +@JSClass struct TS2Swift { + @JSFunction func convert(_ ts: String) throws(JSException) -> String +} diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.swift b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.swift new file mode 100644 index 000000000..6e146dbc3 --- /dev/null +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.swift @@ -0,0 +1,252 @@ +// bridge-js: skip +// 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(BridgeJS) import JavaScriptKit + +extension PlayBridgeJSOutput: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> PlayBridgeJSOutput { + let swiftGlue = String.bridgeJSStackPop() + let importSwiftMacroDecls = String.bridgeJSStackPop() + let outputDts = String.bridgeJSStackPop() + let outputJs = String.bridgeJSStackPop() + return PlayBridgeJSOutput(outputJs: outputJs, outputDts: outputDts, importSwiftMacroDecls: importSwiftMacroDecls, swiftGlue: swiftGlue) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.outputJs.bridgeJSStackPush() + self.outputDts.bridgeJSStackPush() + self.importSwiftMacroDecls.bridgeJSStackPush() + self.swiftGlue.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_PlayBridgeJSOutput(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_PlayBridgeJSOutput())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_PlayBridgeJSOutput") +fileprivate func _bjs_struct_lower_PlayBridgeJSOutput(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_PlayBridgeJSOutput(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_PlayBridgeJSOutput") +fileprivate func _bjs_struct_lift_PlayBridgeJSOutput() -> Int32 +#else +fileprivate func _bjs_struct_lift_PlayBridgeJSOutput() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +extension PlayBridgeJSDiagnostic: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> PlayBridgeJSDiagnostic { + let endColumn = Int.bridgeJSStackPop() + let endLine = Int.bridgeJSStackPop() + let startColumn = Int.bridgeJSStackPop() + let startLine = Int.bridgeJSStackPop() + let message = String.bridgeJSStackPop() + let file = String.bridgeJSStackPop() + return PlayBridgeJSDiagnostic(file: file, message: message, startLine: startLine, startColumn: startColumn, endLine: endLine, endColumn: endColumn) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.file.bridgeJSStackPush() + self.message.bridgeJSStackPush() + self.startLine.bridgeJSStackPush() + self.startColumn.bridgeJSStackPush() + self.endLine.bridgeJSStackPush() + self.endColumn.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_PlayBridgeJSDiagnostic(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_PlayBridgeJSDiagnostic())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_PlayBridgeJSDiagnostic") +fileprivate func _bjs_struct_lower_PlayBridgeJSDiagnostic(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_PlayBridgeJSDiagnostic(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_PlayBridgeJSDiagnostic") +fileprivate func _bjs_struct_lift_PlayBridgeJSDiagnostic() -> Int32 +#else +fileprivate func _bjs_struct_lift_PlayBridgeJSDiagnostic() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +extension PlayBridgeJSResult: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> PlayBridgeJSResult { + let diagnostics = [PlayBridgeJSDiagnostic].bridgeJSStackPop() + let output = Optional.bridgeJSStackPop() + return PlayBridgeJSResult(output: output, diagnostics: diagnostics) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.output.bridgeJSStackPush() + self.diagnostics.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_PlayBridgeJSResult(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_PlayBridgeJSResult())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_PlayBridgeJSResult") +fileprivate func _bjs_struct_lower_PlayBridgeJSResult(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_PlayBridgeJSResult(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_PlayBridgeJSResult") +fileprivate func _bjs_struct_lift_PlayBridgeJSResult() -> Int32 +#else +fileprivate func _bjs_struct_lift_PlayBridgeJSResult() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_PlayBridgeJS_init") +@_cdecl("bjs_PlayBridgeJS_init") +public func _bjs_PlayBridgeJS_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = PlayBridgeJS() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PlayBridgeJS_updateDetailed") +@_cdecl("bjs_PlayBridgeJS_updateDetailed") +public func _bjs_PlayBridgeJS_updateDetailed(_ _self: UnsafeMutableRawPointer, _ swiftSourceBytes: Int32, _ swiftSourceLength: Int32, _ dtsSourceBytes: Int32, _ dtsSourceLength: Int32) -> Void { + #if arch(wasm32) + do { + let ret = try PlayBridgeJS.bridgeJSLiftParameter(_self).updateDetailed(swiftSource: String.bridgeJSLiftParameter(swiftSourceBytes, swiftSourceLength), dtsSource: String.bridgeJSLiftParameter(dtsSourceBytes, dtsSourceLength)) + return ret.bridgeJSLowerReturn() + } catch let error { + if let error = error.thrownValue.object { + withExtendedLifetime(error) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } else { + let jsError = JSError(message: String(describing: error)) + withExtendedLifetime(jsError.jsObject) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } + return + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PlayBridgeJS_deinit") +@_cdecl("bjs_PlayBridgeJS_deinit") +public func _bjs_PlayBridgeJS_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension PlayBridgeJS: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_PlayBridgeJS_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "PlayBridgeJS", name: "bjs_PlayBridgeJS_wrap") +fileprivate func _bjs_PlayBridgeJS_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_PlayBridgeJS_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "PlayBridgeJS", name: "bjs_createTS2Swift") +fileprivate func bjs_createTS2Swift() -> Int32 +#else +fileprivate func bjs_createTS2Swift() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$createTS2Swift() throws(JSException) -> TS2Swift { + let ret = bjs_createTS2Swift() + if let error = _swift_js_take_exception() { + throw error + } + return TS2Swift.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "PlayBridgeJS", name: "bjs_TS2Swift_convert") +fileprivate func bjs_TS2Swift_convert(_ self: Int32, _ ts: Int32) -> Int32 +#else +fileprivate func bjs_TS2Swift_convert(_ self: Int32, _ ts: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$TS2Swift_convert(_ self: JSObject, _ ts: String) throws(JSException) -> String { + let selfValue = self.bridgeJSLowerParameter() + let tsValue = ts.bridgeJSLowerParameter() + let ret = bjs_TS2Swift_convert(selfValue, tsValue) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} \ No newline at end of file diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.ExportSwift.json b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.ExportSwift.json deleted file mode 100644 index e83af9fe9..000000000 --- a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.ExportSwift.json +++ /dev/null @@ -1,125 +0,0 @@ -{ - "classes" : [ - { - "constructor" : { - "abiName" : "bjs_PlayBridgeJS_init", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "parameters" : [ - - ] - }, - "methods" : [ - { - "abiName" : "bjs_PlayBridgeJS_update", - "effects" : { - "isAsync" : false, - "isThrows" : true - }, - "name" : "update", - "parameters" : [ - { - "label" : "swiftSource", - "name" : "swiftSource", - "type" : { - "string" : { - - } - } - }, - { - "label" : "dtsSource", - "name" : "dtsSource", - "type" : { - "string" : { - - } - } - } - ], - "returnType" : { - "swiftHeapObject" : { - "_0" : "PlayBridgeJSOutput" - } - } - } - ], - "name" : "PlayBridgeJS" - }, - { - "methods" : [ - { - "abiName" : "bjs_PlayBridgeJSOutput_outputJs", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "outputJs", - "parameters" : [ - - ], - "returnType" : { - "string" : { - - } - } - }, - { - "abiName" : "bjs_PlayBridgeJSOutput_outputDts", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "outputDts", - "parameters" : [ - - ], - "returnType" : { - "string" : { - - } - } - }, - { - "abiName" : "bjs_PlayBridgeJSOutput_importSwiftGlue", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "importSwiftGlue", - "parameters" : [ - - ], - "returnType" : { - "string" : { - - } - } - }, - { - "abiName" : "bjs_PlayBridgeJSOutput_exportSwiftGlue", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "exportSwiftGlue", - "parameters" : [ - - ], - "returnType" : { - "string" : { - - } - } - } - ], - "name" : "PlayBridgeJSOutput" - } - ], - "functions" : [ - - ], - "moduleName" : "PlayBridgeJS" -} \ No newline at end of file diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.ImportTS.json b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.ImportTS.json deleted file mode 100644 index f1a567cde..000000000 --- a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.ImportTS.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "children" : [ - { - "functions" : [ - { - "name" : "createTS2Skeleton", - "parameters" : [ - - ], - "returnType" : { - "jsObject" : { - "_0" : "TS2Skeleton" - } - } - } - ], - "types" : [ - { - "methods" : [ - { - "name" : "convert", - "parameters" : [ - { - "name" : "ts", - "type" : { - "string" : { - - } - } - } - ], - "returnType" : { - "string" : { - - } - } - } - ], - "name" : "TS2Skeleton", - "properties" : [ - - ] - } - ] - } - ], - "moduleName" : "PlayBridgeJS" -} \ No newline at end of file diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.json b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.json new file mode 100644 index 000000000..3046e1f01 --- /dev/null +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.json @@ -0,0 +1,282 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_PlayBridgeJS_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_PlayBridgeJS_updateDetailed", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "updateDetailed", + "parameters" : [ + { + "label" : "swiftSource", + "name" : "swiftSource", + "type" : { + "string" : { + + } + } + }, + { + "label" : "dtsSource", + "name" : "dtsSource", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "PlayBridgeJSResult" + } + } + } + ], + "name" : "PlayBridgeJS", + "properties" : [ + + ], + "swiftCallName" : "PlayBridgeJS" + } + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + { + "methods" : [ + + ], + "name" : "PlayBridgeJSOutput", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "outputJs", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "outputDts", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "importSwiftMacroDecls", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "swiftGlue", + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "PlayBridgeJSOutput" + }, + { + "methods" : [ + + ], + "name" : "PlayBridgeJSDiagnostic", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "file", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "message", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "startLine", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "startColumn", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "endLine", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "endColumn", + "type" : { + "int" : { + + } + } + } + ], + "swiftCallName" : "PlayBridgeJSDiagnostic" + }, + { + "methods" : [ + + ], + "name" : "PlayBridgeJSResult", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "output", + "type" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "PlayBridgeJSOutput" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "diagnostics", + "type" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "PlayBridgeJSDiagnostic" + } + } + } + } + } + ], + "swiftCallName" : "PlayBridgeJSResult" + } + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "createTS2Swift", + "parameters" : [ + + ], + "returnType" : { + "jsObject" : { + "_0" : "TS2Swift" + } + } + } + ], + "types" : [ + { + "getters" : [ + + ], + "methods" : [ + { + "name" : "convert", + "parameters" : [ + { + "name" : "ts", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "TS2Swift", + "setters" : [ + + ], + "staticMethods" : [ + + ] + } + ] + } + ] + }, + "moduleName" : "PlayBridgeJS" +} \ No newline at end of file diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/bridge-js.d.ts b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/bridge-js.d.ts index 44e79a5cb..7173fab8e 100644 --- a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/bridge-js.d.ts +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/bridge-js.d.ts @@ -1,5 +1,5 @@ -export interface TS2Skeleton { +export interface TS2Swift { convert(ts: string): string; } -export function createTS2Skeleton(): TS2Skeleton; \ No newline at end of file +export function createTS2Swift(): TS2Swift; \ No newline at end of file diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/main.swift b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/main.swift index 35d2340d2..ec9eda774 100644 --- a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/main.swift +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/main.swift @@ -1,14 +1,40 @@ import JavaScriptEventLoop import JavaScriptKit import SwiftParser +import SwiftSyntax import class Foundation.JSONDecoder @JS class PlayBridgeJS { @JS init() {} - @JS func update(swiftSource: String, dtsSource: String) throws(JSException) -> PlayBridgeJSOutput { + /// Structured entry point used by the playground so JS doesn't need to parse diagnostics. + @JS func updateDetailed(swiftSource: String, dtsSource: String) throws(JSException) -> PlayBridgeJSResult { do { - return try _update(swiftSource: swiftSource, dtsSource: dtsSource) + let output = try _update(swiftSource: swiftSource, dtsSource: dtsSource) + return PlayBridgeJSResult(output: output, diagnostics: []) + } catch let error as BridgeJSCoreDiagnosticError { + let diagnostics = error.diagnostics.map { diag -> PlayBridgeJSDiagnostic in + let converter = SourceLocationConverter(fileName: diag.file, tree: diag.diagnostic.node.root) + let start = converter.location(for: diag.diagnostic.node.positionAfterSkippingLeadingTrivia) + let end = converter.location(for: diag.diagnostic.node.endPositionBeforeTrailingTrivia) + + let startLine = start.line + let startColumn = start.column + let endLine = end.line + let endColumn = max(startColumn + 1, end.column) + + return PlayBridgeJSDiagnostic( + file: diag.file, + message: diag.diagnostic.message, + startLine: startLine, + startColumn: startColumn, + endLine: endLine, + endColumn: endColumn + ) + } + return PlayBridgeJSResult(output: nil, diagnostics: diagnostics) + } catch let error as BridgeJSCoreError { + throw JSException(message: error.description) } catch let error as JSException { throw error } catch { @@ -17,57 +43,58 @@ import class Foundation.JSONDecoder } func _update(swiftSource: String, dtsSource: String) throws -> PlayBridgeJSOutput { - let exportSwift = ExportSwift(progress: .silent, moduleName: "Playground") - let sourceFile = Parser.parse(source: swiftSource) - try exportSwift.addSourceFile(sourceFile, "Playground.swift") - let exportResult = try exportSwift.finalize() - var importTS = ImportTS(progress: .silent, moduleName: "Playground") - let ts2skeleton = try createTS2Skeleton() - let skeletonJSONString = try ts2skeleton.convert(dtsSource) - let decoder = JSONDecoder() - let importSkeleton = try decoder.decode( - ImportedFileSkeleton.self, - from: skeletonJSONString.data(using: .utf8)! - ) - importTS.addSkeleton(importSkeleton) - let importSwiftGlue = try importTS.finalize() + let moduleName = "Playground" - let linker = BridgeJSLink( - exportedSkeletons: exportResult.map { [$0.outputSkeleton] } ?? [], - importedSkeletons: [ - ImportedModuleSkeleton( - moduleName: "Playground", - children: [importSkeleton] - ) - ], - sharedMemory: false + let swiftToSkeleton = SwiftToSkeleton(progress: .silent, moduleName: moduleName, exposeToGlobal: false) + swiftToSkeleton.addSourceFile(Parser.parse(source: swiftSource), inputFilePath: "Playground.swift") + + let ts2swift = try createTS2Swift() + let importSwiftMacroDecls = try ts2swift.convert(dtsSource) + swiftToSkeleton.addSourceFile( + Parser.parse(source: importSwiftMacroDecls), + inputFilePath: "Playground.Macros.swift" ) + + let skeleton = try swiftToSkeleton.finalize() + + let exportResult = try skeleton.exported.flatMap { + let exportSwift = ExportSwift(progress: .silent, moduleName: moduleName, skeleton: $0) + return try exportSwift.finalize() + } + let importResult = try skeleton.imported.flatMap { + let importTS = ImportTS(progress: .silent, moduleName: moduleName, skeleton: $0) + return try importTS.finalize() + } + let linker = BridgeJSLink(skeletons: [skeleton], sharedMemory: false) let linked = try linker.link() return PlayBridgeJSOutput( outputJs: linked.outputJs, outputDts: linked.outputDts, - importSwiftGlue: importSwiftGlue ?? "", - exportSwiftGlue: exportResult?.outputSwift ?? "" + importSwiftMacroDecls: importSwiftMacroDecls, + swiftGlue: (importResult ?? "") + "\n\n" + (exportResult ?? "") ) } + } -@JS class PlayBridgeJSOutput { - let _outputJs: String - let _outputDts: String - let _importSwiftGlue: String - let _exportSwiftGlue: String +@JS struct PlayBridgeJSOutput { + let outputJs: String + let outputDts: String + let importSwiftMacroDecls: String + let swiftGlue: String +} - init(outputJs: String, outputDts: String, importSwiftGlue: String, exportSwiftGlue: String) { - self._outputJs = outputJs - self._outputDts = outputDts - self._importSwiftGlue = importSwiftGlue - self._exportSwiftGlue = exportSwiftGlue - } +@JS struct PlayBridgeJSDiagnostic { + let file: String + let message: String + let startLine: Int + let startColumn: Int + let endLine: Int + let endColumn: Int +} - @JS func outputJs() -> String { self._outputJs } - @JS func outputDts() -> String { self._outputDts } - @JS func importSwiftGlue() -> String { self._importSwiftGlue } - @JS func exportSwiftGlue() -> String { self._exportSwiftGlue } +@JS struct PlayBridgeJSResult { + let output: PlayBridgeJSOutput? + let diagnostics: [PlayBridgeJSDiagnostic] } diff --git a/Examples/PlayBridgeJS/build.sh b/Examples/PlayBridgeJS/build.sh index c4dc8d71f..31c07896c 100755 --- a/Examples/PlayBridgeJS/build.sh +++ b/Examples/PlayBridgeJS/build.sh @@ -1,3 +1,5 @@ #!/bin/bash set -euxo pipefail -env JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasi:-${SWIFT_SDK_ID:-wasm32-unknown-wasi}}" -c "${1:-debug}" js --use-cdn +swift package --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1}}" \ + plugin --allow-writing-to-package-directory \ + js --use-cdn --output ./Bundle -c "${1:-debug}" diff --git a/Examples/PlayBridgeJS/index.html b/Examples/PlayBridgeJS/index.html index 2a5841329..1dd07fe2a 100644 --- a/Examples/PlayBridgeJS/index.html +++ b/Examples/PlayBridgeJS/index.html @@ -9,7 +9,8 @@ @@ -41,6 +42,12 @@

Share Your Code

+ @@ -77,15 +84,15 @@

Output

+ - - +
-
-
+
+
-
-
+
+
diff --git a/Examples/PlayBridgeJS/package.json b/Examples/PlayBridgeJS/package.json new file mode 100644 index 000000000..2feb6565f --- /dev/null +++ b/Examples/PlayBridgeJS/package.json @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "@typescript/vfs": "^1.6.1" + } +} diff --git a/Examples/Testing/README.md b/Examples/Testing/README.md index 2f28357a6..ae1c68b6f 100644 --- a/Examples/Testing/README.md +++ b/Examples/Testing/README.md @@ -31,3 +31,10 @@ llvm-cov show -instr-profile=.build/plugins/PackageToJS/outputs/PackageTests/def ```console npx serve .build/coverage/html ``` +## Customize test harness + +See [./run-tests-with-browser-options.mjs](./run-tests-with-browser-options.mjs) for an example of customizing the test harness to run tests with specific browser options. + +```console +node run-tests-with-browser-options.mjs +``` diff --git a/Examples/Testing/run-tests-with-browser-options.mjs b/Examples/Testing/run-tests-with-browser-options.mjs new file mode 100644 index 000000000..9051c28c8 --- /dev/null +++ b/Examples/Testing/run-tests-with-browser-options.mjs @@ -0,0 +1,23 @@ +// Import the generated test harness function +import { testBrowser } from "./.build/plugins/PackageToJS/outputs/PackageTests/test.js" + +// Execute the test with custom browser options +async function runTest(args) { + const exitCode = await testBrowser({ + args: args, + playwright: { + browser: "chromium", + launchOptions: { + headless: false, + } + } + }); + if (exitCode !== 0) { + process.exit(exitCode); + } +} +// Run XCTest test suites +await runTest([]); +// Run Swift Testing test suites +await runTest(["--testing-library", "swift-testing"]); +process.exit(0); diff --git a/Makefile b/Makefile index 5ac35ea57..270eb9b36 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,9 @@ -SWIFT_SDK_ID ?= wasm32-unknown-wasi +SWIFT_SDK_ID ?= +ifeq ($(JAVASCRIPTKIT_DISABLE_TRACING_TRAIT),1) + TRACING_ARGS := +else + TRACING_ARGS := --traits Tracing +endif .PHONY: bootstrap bootstrap: @@ -7,12 +12,13 @@ bootstrap: .PHONY: unittest unittest: @echo Running unit tests - env JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --swift-sdk "$(SWIFT_SDK_ID)" \ + @test -n "$(SWIFT_SDK_ID)" || { \ + echo "SWIFT_SDK_ID is not set. Run 'swift sdk list' and pass a matching SDK, e.g. 'make unittest SWIFT_SDK_ID='."; \ + exit 2; \ + } + swift package --swift-sdk "$(SWIFT_SDK_ID)" \ + $(TRACING_ARGS) \ --disable-sandbox \ - -Xlinker --stack-first \ - -Xlinker --global-base=524288 \ - -Xlinker -z \ - -Xlinker stack-size=524288 \ js test --prelude ./Tests/prelude.mjs -Xnode --expose-gc .PHONY: regenerate_swiftpm_resources diff --git a/Package.swift b/Package.swift index 44d371669..60adb7a5f 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:6.0 +// swift-tools-version:6.1 import CompilerPluginSupport import PackageDescription @@ -8,10 +8,22 @@ let shouldBuildForEmbedded = Context.environment["JAVASCRIPTKIT_EXPERIMENTAL_EMB let useLegacyResourceBundling = Context.environment["JAVASCRIPTKIT_USE_LEGACY_RESOURCE_BUNDLING"].flatMap(Bool.init) ?? false +let testingLinkerFlags: [LinkerSetting] = [ + .unsafeFlags( + [ + "-Xlinker", "--stack-first", + "-Xlinker", "--global-base=524288", + "-Xlinker", "-z", + "-Xlinker", "stack-size=524288", + ], + .when(platforms: [.wasi]) + ) +] + let package = Package( name: "JavaScriptKit", platforms: [ - .macOS(.v10_15), + .macOS(.v13), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), @@ -28,12 +40,12 @@ let package = Package( .plugin(name: "BridgeJSCommandPlugin", targets: ["BridgeJSCommandPlugin"]), ], dependencies: [ - .package(url: "https://github.com/swiftlang/swift-syntax", "600.0.0"..<"601.0.0") + .package(url: "https://github.com/swiftlang/swift-syntax", "600.0.0"..<"603.0.0") ], targets: [ .target( name: "JavaScriptKit", - dependencies: ["_CJavaScriptKit"], + dependencies: ["_CJavaScriptKit", "BridgeJSMacros"], exclude: useLegacyResourceBundling ? [] : ["Runtime"], resources: useLegacyResourceBundling ? [.copy("Runtime")] : [], cSettings: shouldBuildForEmbedded @@ -50,12 +62,21 @@ let package = Package( ] : []) ), .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") - ] + ], + linkerSettings: testingLinkerFlags ), .target( @@ -70,7 +91,8 @@ let package = Package( .target(name: "_CJavaScriptBigIntSupport", dependencies: ["_CJavaScriptKit"]), .testTarget( name: "JavaScriptBigIntSupportTests", - dependencies: ["JavaScriptBigIntSupport", "JavaScriptKit"] + dependencies: ["JavaScriptBigIntSupport", "JavaScriptKit"], + linkerSettings: testingLinkerFlags ), .target( @@ -92,7 +114,8 @@ let package = Package( ], swiftSettings: [ .enableExperimentalFeature("Extern") - ] + ], + linkerSettings: testingLinkerFlags ), .target( name: "JavaScriptEventLoopTestSupport", @@ -107,7 +130,8 @@ let package = Package( dependencies: [ "JavaScriptKit", "JavaScriptEventLoopTestSupport", - ] + ], + linkerSettings: testingLinkerFlags ), .target( name: "JavaScriptFoundationCompat", @@ -119,7 +143,8 @@ let package = Package( name: "JavaScriptFoundationCompatTests", dependencies: [ "JavaScriptFoundationCompat" - ] + ], + linkerSettings: testingLinkerFlags ), .plugin( name: "PackageToJS", @@ -151,7 +176,7 @@ let package = Package( .product(name: "SwiftBasicFormat", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), ], - exclude: ["TS2Skeleton/JavaScript", "README.md"] + exclude: ["TS2Swift/JavaScript", "README.md"] ), .testTarget( name: "BridgeJSRuntimeTests", @@ -159,11 +184,27 @@ let package = Package( exclude: [ "bridge-js.config.json", "bridge-js.d.ts", + "bridge-js.global.d.ts", "Generated/JavaScript", + "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/Package@swift-6.2.swift b/Package@swift-6.2.swift new file mode 100644 index 000000000..20583865b --- /dev/null +++ b/Package@swift-6.2.swift @@ -0,0 +1,221 @@ +// 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", + ], + .when(platforms: [.wasi]) + ) +] + +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", + "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 9ac96d953..2074a8a66 100644 --- a/Plugins/BridgeJS/Package.swift +++ b/Plugins/BridgeJS/Package.swift @@ -1,12 +1,17 @@ // swift-tools-version: 6.0 +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"), ], targets: [ .target(name: "BridgeJSBuildPlugin"), @@ -14,11 +19,11 @@ let package = Package( name: "BridgeJSTool", dependencies: [ "BridgeJSCore", - "TS2Skeleton", + "TS2Swift", ] ), .target( - name: "TS2Skeleton", + name: "TS2Swift", dependencies: [ "BridgeJSCore", "BridgeJSSkeleton", @@ -29,6 +34,7 @@ let package = Package( name: "BridgeJSCore", dependencies: [ "BridgeJSSkeleton", + "BridgeJSUtilities", .product(name: "SwiftParser", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftBasicFormat", package: "swift-syntax"), @@ -36,10 +42,14 @@ let package = Package( ] ), .target(name: "BridgeJSSkeleton"), + .target(name: "BridgeJSUtilities"), .target( name: "BridgeJSLink", - dependencies: ["BridgeJSSkeleton"] + dependencies: [ + "BridgeJSSkeleton", + "BridgeJSUtilities", + ] ), .testTarget( @@ -47,9 +57,34 @@ let package = Package( dependencies: [ "BridgeJSCore", "BridgeJSLink", - "TS2Skeleton", + "TS2Swift", + .product(name: "SwiftParser", package: "swift-syntax"), + .product(name: "SwiftSyntax", package: "swift-syntax"), ], exclude: ["__Snapshots__", "Inputs"] ), + .macro( + name: "BridgeJSMacros", + dependencies: [ + .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), + .product(name: "SwiftCompilerPlugin", package: "swift-syntax"), + ] + ), + .testTarget( + name: "BridgeJSMacrosTests", + dependencies: [ + "BridgeJSMacros", + .product(name: "SwiftSyntaxMacrosGenericTestSupport", package: "swift-syntax"), + ] + ), + + .executableTarget( + name: "BridgeJSToolInternal", + dependencies: [ + "BridgeJSCore", + "BridgeJSLink", + .product(name: "ArgumentParser", package: "swift-argument-parser"), + ] + ), ] ) diff --git a/Plugins/BridgeJS/README.md b/Plugins/BridgeJS/README.md index f762c294b..9e1e0aa08 100644 --- a/Plugins/BridgeJS/README.md +++ b/Plugins/BridgeJS/README.md @@ -1,46 +1,52 @@ # BridgeJS > [!IMPORTANT] -> This feature is still experimental, and the API may change frequently. Use at your own risk with `JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1` environment variable. +> This feature is still experimental, and the API may change frequently. Use at your own risk. > [!NOTE] -> This documentation is intended for JavaScriptKit developers, not JavaScriptKit users. +> This documentation is intended for JavaScriptKit developers, not JavaScriptKit users. For user documentation, see [Introducing BridgeJS](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/introducing-bridgejs), [Setting up BridgeJS](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/setting-up-bridgejs), [Exporting Swift to JavaScript](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/exporting-swift-to-javascript), [Importing JavaScript into Swift](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/importing-javascript-into-swift), and [Generating bindings from TypeScript](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/generating-from-typescript). ## Overview BridgeJS provides easy interoperability between Swift and JavaScript/TypeScript. It enables: -1. **Importing TypeScript APIs into Swift**: Use TypeScript/JavaScript APIs directly from Swift code -2. **Exporting Swift APIs to JavaScript**: Make your Swift APIs available to JavaScript code +1. **Export Swift to JavaScript** - Expose Swift functions, classes, and types to JavaScript; the plugin generates TypeScript definitions (`.d.ts`) for the exported API. +2. **Import JavaScript into Swift** - Make JavaScript/TypeScript APIs callable from Swift with macro-annotated bindings or bindings generated from a TypeScript declaration file (`bridge-js.d.ts`). + +The workflow is: + +1. `ts2swift` converts TypeScript definitions (`bridge-js.d.ts`) to macro-annotated Swift declarations (`BridgeJS.Macros.swift`) +2. `bridge-js generate` processes both Swift source files (for export) and macro-annotated Swift files (for import) to generate: + - `BridgeJS.swift` (Swift glue code) + - `JavaScript/BridgeJS.json` (a unified skeleton for linking) +3. `bridge-js link` combines module skeletons (`JavaScript/BridgeJS.json`) to produce JavaScript glue code (`bridge-js.js` and `bridge-js.d.ts`) ## Architecture Diagram ```mermaid graph LR - E1 --> G3[ExportSwift.json] subgraph ModuleA - A.swift --> E1[[bridge-js export]] - B.swift --> E1 - E1 --> G1[ExportSwift.swift] - B1[bridge-js.d.ts]-->I1[[bridge-js import]] - I1 --> G2[ImportTS.swift] + A.swift --> G1[bridge-js generate] + B.swift --> G1 + B1[bridge-js.d.ts] --> T1[[ts2swift]] + T1 --> M1[BridgeJS.Macros.swift] + M1 --> G1 + G1 --> G3[BridgeJS.json] + G1 --> G2[BridgeJS.swift] end - I1 --> G4[ImportTS.json] - E2 --> G7[ExportSwift.json] subgraph ModuleB - C.swift --> E2[[bridge-js export]] - D.swift --> E2 - E2 --> G5[ExportSwift.swift] - B2[bridge-js.d.ts]-->I2[[bridge-js import]] - I2 --> G6[ImportTS.swift] + C.swift --> G4[bridge-js generate] + D.swift --> G4 + B2[bridge-js.d.ts] --> T2[[ts2swift]] + T2 --> M2[BridgeJS.Macros.swift] + M2 --> G4 + G4 --> G5[BridgeJS.swift] + G4 --> G6[BridgeJS.json] end - I2 --> G8[ImportTS.json] G3 --> L1[[bridge-js link]] - G4 --> L1 - G7 --> L1 - G8 --> L1 + G6 --> L1 L1 --> F1[bridge-js.js] L1 --> F2[bridge-js.d.ts] @@ -54,27 +60,53 @@ graph LR ## Type Mapping -### Primitive Type Conversions - -TBD - -| Swift Type | JS Type | Wasm Core Type | -|:--------------|:-----------|:---------------| -| `Int` | `number` | `i32` | -| `UInt` | `number` | `i32` | -| `Int8` | `number` | `i32` | -| `UInt8` | `number` | `i32` | -| `Int16` | `number` | `i32` | -| `UInt16` | `number` | `i32` | -| `Int32` | `number` | `i32` | -| `UInt32` | `number` | `i32` | -| `Int64` | `bigint` | `i64` | -| `UInt64` | `bigint` | `i64` | -| `Float` | `number` | `f32` | -| `Double` | `number` | `f64` | -| `Bool` | `boolean` | `i32` | -| `Void` | `void` | - | -| `String` | `string` | `i32` | +### Primitive Types + +| Swift Type | TypeScript Type | Wasm Core Type | +|:--------------|:----------------|:---------------| +| `Int` | `number` | `i32` | +| `UInt` | `number` | `i32` | +| `Int8` | `number` | `i32` | +| `UInt8` | `number` | `i32` | +| `Int16` | `number` | `i32` | +| `UInt16` | `number` | `i32` | +| `Int32` | `number` | `i32` | +| `UInt32` | `number` | `i32` | +| `Int64` | `bigint` | `i64` | +| `UInt64` | `bigint` | `i64` | +| `Float` | `number` | `f32` | +| `Double` | `number` | `f64` | +| `Bool` | `boolean` | `i32` | +| `Void` | `void` | - | + +### Complex Types + +| Swift Type | TypeScript Type | Semantics | Status | +|:-----------|:----------------|:----------|:-------| +| `String` | `string` | Copy | ✅ | +| `@JS class` | `interface` + constructor | Reference (pointer) | ✅ | +| `@JS struct` | `interface` | Copy (fields via stacks) | ✅ | +| `@JS enum` (case) | const object + tag type | Copy (integer) | ✅ | +| `@JS enum` (raw value) | const object + tag type | Copy (raw value) | ✅ | +| `@JS enum` (associated) | discriminated union | Copy (fields via stacks) | ✅ | +| `@JS protocol` | `interface` | Reference (wrapper) | ✅ | +| `Optional` | `T \| null` | Depends on T | ✅ | +| `(T) -> U` | `(arg: T) => U` | Reference (boxed) | ✅ | +| `JSObject` | `any` / `object` | Reference | ✅ | +| `Array` | `T[]` | Copy | ✅ | +| `Array>` | `T[][]` | Copy | ✅ | +| `Dictionary` | `Record` | - | [#495](https://github.com/swiftwasm/JavaScriptKit/issues/495) | +| `Set` | `Set` | - | [#397](https://github.com/swiftwasm/JavaScriptKit/issues/397) | +| `Foundation.URL` | `string` | - | [#496](https://github.com/swiftwasm/JavaScriptKit/issues/496) | +| Generics | - | - | [#398](https://github.com/swiftwasm/JavaScriptKit/issues/398) | + +### Import-specific (TypeScript -> Swift) + +| TypeScript Type | Swift Type | Status | +|:----------------|:-----------|:-------| +| `T \| null` | `Optional` | [#475](https://github.com/swiftwasm/JavaScriptKit/issues/475) | +| `T \| undefined` | `Optional` | [#475](https://github.com/swiftwasm/JavaScriptKit/issues/475) | +| `enum` | `@JS enum` | [#489](https://github.com/swiftwasm/JavaScriptKit/issues/489) | ## Type Modeling @@ -104,23 +136,63 @@ The ABI will not be stable, and not meant to be interposed by other tools. ### Parameter Passing -Parameter passing follows Wasm calling conventions, with custom handling for complex types like strings and objects. +Parameter passing follows Wasm calling conventions, with custom handling for complex types: -TBD +- **Primitives**: Passed directly as Wasm arguments (`i32`, `i64`, `f32`, `f64`) +- **Strings**: UTF-8 bytes stored in `swift.memory`, ID + length passed as Wasm arguments +- **Swift Classes**: Raw Swift heap pointer passed as `i32` +- **JSObjects**: Object stored in `swift.memory.heap`, object ID passed as `i32` +- **Structs/Arrays**: Fields/elements pushed to type-specific stacks, Swift pops in reverse order +- **Closures**: Boxed and retained in memory, handle passed as `i32` ### Return Values -TBD +Return values use direct Wasm returns for primitives, and imported intrinsic functions for complex types: + +- **Primitives**: Returned directly via Wasm return value +- **Strings**: Swift writes UTF-8 bytes to shared memory, JS decodes +- **Swift Classes**: Pointer returned directly, JS wraps in `SwiftHeapObject` with `FinalizationRegistry` +- **Structs/Arrays**: Swift pushes fields/elements to type-specific stacks, JS reconstructs + +### Memory Management + +- **Swift Classes**: Live on Swift heap. JS holds pointer wrapped in `SwiftHeapObject`. `FinalizationRegistry` calls `deinit` on GC. Optional `release()` for deterministic cleanup. +- **JSObjects**: Live in `swift.memory.heap` (JS side). Swift holds ID wrapped in `JSObject`. Reference counted via `retain`/`release`. +- **Structs/Arrays/Enums**: Copy semantics - data serialized across boundary. No cleanup needed. +- **Closures**: Boxed on source side, released when GC'd on either side. + +For detailed semantics, see the [How It Works sections](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/exporting-swift-class#how-it-works) in the user documentation. + +## Testing + +- **Full BridgeJS tests** (Swift + TS2Swift Vitest): `swift test --package-path ./Plugins/BridgeJS` +- **TS2Swift only** (fast iteration on `.d.ts` -> Swift): `npm -C Sources/TS2Swift/JavaScript test` +- **Regenerate snapshot artifacts**: `UPDATE_SNAPSHOTS=1 swift test --package-path ./Plugins/BridgeJS` + +## Debug utilities + +`BridgeJSToolInternal` exposes pipeline stages for debugging: + +- `emit-skeleton` - Parse Swift files (or `-` for stdin) and print the BridgeJS skeleton as JSON. +- `emit-swift-thunks` - Read skeleton JSON (from a file or `-` for stdin) and print the generated Swift glue (export and import thunks). +- `emit-js` / `emit-dts` - Read skeleton JSON files (or `-` for stdin) and print the .js/.d.ts + +Use these to inspect parser output and generated code without running the full generate/link pipeline. + +```console +$ cat < Int +@JS class Bar { + @JS init() {} + @JS func baz() {} +} +EOS +``` ## Future Work -- [ ] Struct on parameter or return type -- [ ] Throws functions -- [ ] Async functions - [ ] Cast between TS interface -- [ ] Closure support -- [ ] Simplify constructor pattern - * https://github.com/ocsigen/ts2ocaml/blob/main/docs/js_of_ocaml.md#feature-immediate-constructor +- [ ] Simplify constructor pattern ([reference](https://github.com/ocsigen/ts2ocaml/blob/main/docs/js_of_ocaml.md#feature-immediate-constructor)) ```typescript interface Foo = { someMethod(value: number): void; @@ -135,4 +207,9 @@ TBD declare var Foo: FooConstructor; ``` - [ ] Use `externref` once it's widely available -- [ ] Test SwiftObject roundtrip \ No newline at end of file +- [ ] Test SwiftObject roundtrip +- [ ] Import TS `enum` as Swift enum ([#489](https://github.com/swiftwasm/JavaScriptKit/issues/489)) +- [ ] Support `T | null` and `T | undefined` imports ([#475](https://github.com/swiftwasm/JavaScriptKit/issues/475)) +- [ ] Support `@JS var` for global scope imports ([#466](https://github.com/swiftwasm/JavaScriptKit/issues/466)) +- [ ] Support `export { thing } from 'pkg'` form ([#437](https://github.com/swiftwasm/JavaScriptKit/issues/437)) +- [ ] Support imported TS type usage on exported interface ([#497](https://github.com/swiftwasm/JavaScriptKit/issues/497)) diff --git a/Plugins/BridgeJS/Sources/BridgeJSBuildPlugin/BridgeJSBuildPlugin.swift b/Plugins/BridgeJS/Sources/BridgeJSBuildPlugin/BridgeJSBuildPlugin.swift index 9ea095205..3cb6dc860 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSBuildPlugin/BridgeJSBuildPlugin.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSBuildPlugin/BridgeJSBuildPlugin.swift @@ -11,93 +11,67 @@ struct BridgeJSBuildPlugin: BuildToolPlugin { guard let swiftSourceModuleTarget = target as? SwiftSourceModuleTarget else { return [] } - var commands: [Command] = [] - commands.append(try createExportSwiftCommand(context: context, target: swiftSourceModuleTarget)) - if let importCommand = try createImportTSCommand(context: context, target: swiftSourceModuleTarget) { - commands.append(importCommand) - } - return commands + return [try createGenerateCommand(context: context, target: swiftSourceModuleTarget)] } private func pathToConfigFile(target: SwiftSourceModuleTarget) -> URL { return target.directoryURL.appending(path: "bridge-js.config.json") } - private func createExportSwiftCommand(context: PluginContext, target: SwiftSourceModuleTarget) throws -> Command { - let outputSwiftPath = context.pluginWorkDirectoryURL.appending(path: "BridgeJS.ExportSwift.swift") - let outputSkeletonPath = context.pluginWorkDirectoryURL.appending(path: "BridgeJS.ExportSwift.json") + private func createGenerateCommand(context: PluginContext, target: SwiftSourceModuleTarget) throws -> Command { + let outputSwiftPath = context.pluginWorkDirectoryURL.appending(path: "BridgeJS.swift") + let inputSwiftFiles = target.sourceFiles.filter { !$0.url.path.hasPrefix(context.pluginWorkDirectoryURL.path + "/") } .map(\.url) + let configFile = pathToConfigFile(target: target) - let inputFiles: [URL] + var inputFiles: [URL] = inputSwiftFiles if FileManager.default.fileExists(atPath: configFile.path) { - inputFiles = inputSwiftFiles + [configFile] - } else { - inputFiles = inputSwiftFiles + inputFiles.append(configFile) } - return .buildCommand( - displayName: "Export Swift API", - executable: try context.tool(named: "BridgeJSTool").url, - arguments: [ - "export", - "--module-name", - target.name, - "--output-skeleton", - outputSkeletonPath.path, - "--output-swift", - outputSwiftPath.path, - // Generate the output files even if nothing is exported not to surprise - // the build system. - "--always-write", "true", - ] + inputSwiftFiles.map(\.path), - inputFiles: inputFiles, - outputFiles: [ - outputSwiftPath - ] - ) - } - private func createImportTSCommand(context: PluginContext, target: SwiftSourceModuleTarget) throws -> Command? { - let outputSwiftPath = context.pluginWorkDirectoryURL.appending(path: "BridgeJS.ImportTS.swift") - let outputSkeletonPath = context.pluginWorkDirectoryURL.appending(path: "BridgeJS.ImportTS.json") - let inputTSFile = target.directoryURL.appending(path: "bridge-js.d.ts") - guard FileManager.default.fileExists(atPath: inputTSFile.path) else { - return nil + // Include Swift files generated by other plugins applied to this + // target (available in tools-version 6.0+). This lets BridgeJS + // process @JS annotations in files produced by earlier plugins + // without requiring any extra configuration. + let pluginGeneratedSwiftFiles = target.pluginGeneratedSources.filter { + $0.pathExtension == "swift" } + inputFiles.append(contentsOf: pluginGeneratedSwiftFiles) - let configFile = pathToConfigFile(target: target) - let inputFiles: [URL] - if FileManager.default.fileExists(atPath: configFile.path) { - inputFiles = [inputTSFile, configFile] - } else { - inputFiles = [inputTSFile] + let inputTSFile = target.directoryURL.appending(path: "bridge-js.d.ts") + let tsconfigPath = context.package.directoryURL.appending(path: "tsconfig.json") + + var arguments: [String] = [ + "generate", + "--module-name", + target.name, + "--target-dir", + target.directoryURL.path, + "--output-dir", + context.pluginWorkDirectoryURL.path, + "--always-write", "true", + ] + + if FileManager.default.fileExists(atPath: inputTSFile.path) { + inputFiles.append(contentsOf: [inputTSFile, tsconfigPath]) + arguments.append(contentsOf: [ + "--project", + tsconfigPath.path, + ]) } + + let allSwiftFiles = inputSwiftFiles + pluginGeneratedSwiftFiles + arguments.append(contentsOf: allSwiftFiles.map(\.path)) + return .buildCommand( - displayName: "Import TypeScript API", + displayName: "Generate BridgeJS code", executable: try context.tool(named: "BridgeJSTool").url, - arguments: [ - "import", - "--target-dir", - target.directoryURL.path, - "--output-skeleton", - outputSkeletonPath.path, - "--output-swift", - outputSwiftPath.path, - "--module-name", - target.name, - // Generate the output files even if nothing is imported not to surprise - // the build system. - "--always-write", "true", - "--project", - context.package.directoryURL.appending(path: "tsconfig.json").path, - inputTSFile.path, - ], + arguments: arguments, inputFiles: inputFiles, - outputFiles: [ - outputSwiftPath - ] + outputFiles: [outputSwiftPath] ) } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSCommandPlugin/BridgeJSCommandPlugin.swift b/Plugins/BridgeJS/Sources/BridgeJSCommandPlugin/BridgeJSCommandPlugin.swift index a4a2fcf1e..a45a06188 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCommandPlugin/BridgeJSCommandPlugin.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCommandPlugin/BridgeJSCommandPlugin.swift @@ -97,52 +97,40 @@ extension BridgeJSCommandPlugin.Context { ) throws { printStderr("Generating bridge code for \(target.name)...") - printVerbose("Exporting Swift API for \(target.name)...") - let generatedDirectory = target.directoryURL.appending(path: "Generated") - let generatedJavaScriptDirectory = generatedDirectory.appending(path: "JavaScript") - - try runBridgeJSTool( - arguments: [ - "export", - "--module-name", - target.name, - "--output-skeleton", - generatedJavaScriptDirectory.appending(path: "BridgeJS.ExportSwift.json").path, - "--output-swift", - generatedDirectory.appending(path: "BridgeJS.ExportSwift.swift").path, - "--verbose", - options.verbose ? "true" : "false", - ] - + target.sourceFiles.filter { - !$0.url.path.hasPrefix(generatedDirectory.path + "/") - }.map(\.url.path) + remainingArguments - ) - - printVerbose("Importing TypeScript API for \(target.name)...") let bridgeDtsPath = target.directoryURL.appending(path: "bridge-js.d.ts") - // Execute import only if bridge-js.d.ts exists + let tsconfigPath = context.package.directoryURL.appending(path: "tsconfig.json") + + // Unified generate command + var generateArguments: [String] = [ + "generate", + "--module-name", + target.name, + "--target-dir", + target.directoryURL.path, + "--output-dir", + generatedDirectory.path, + "--verbose", + options.verbose ? "true" : "false", + ] + if FileManager.default.fileExists(atPath: bridgeDtsPath.path) { - try runBridgeJSTool( - arguments: [ - "import", - "--target-dir", - target.directoryURL.path, - "--output-skeleton", - generatedJavaScriptDirectory.appending(path: "BridgeJS.ImportTS.json").path, - "--output-swift", - generatedDirectory.appending(path: "BridgeJS.ImportTS.swift").path, - "--verbose", - options.verbose ? "true" : "false", - "--module-name", - target.name, - "--project", - context.package.directoryURL.appending(path: "tsconfig.json").path, - bridgeDtsPath.path, - ] + remainingArguments - ) + generateArguments.append(contentsOf: [ + "--project", + tsconfigPath.path, + bridgeDtsPath.path, + ]) } + + generateArguments.append( + contentsOf: target.sourceFiles.filter { + !$0.url.path.hasPrefix(generatedDirectory.path + "/") + }.map(\.url.path) + ) + generateArguments.append(contentsOf: remainingArguments) + + try runBridgeJSTool(arguments: generateArguments) } private func runBridgeJSTool(arguments: [String]) throws { diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/BridgeJSConfig.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/BridgeJSConfig.swift deleted file mode 100644 index cf6f881e6..000000000 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/BridgeJSConfig.swift +++ /dev/null @@ -1,55 +0,0 @@ -import struct Foundation.URL -import struct Foundation.Data -import class Foundation.FileManager -import class Foundation.JSONDecoder - -/// Configuration file representation for BridgeJS. -public struct BridgeJSConfig: Codable { - /// A mapping of tool names to their override paths. - /// - /// If not present, the tool will be searched for in the system PATH. - public var tools: [String: String]? - - /// Load the configuration file from the SwiftPM package target directory. - /// - /// Files are loaded **in this order** and merged (later files override earlier ones): - /// 1. `bridge-js.config.json` - /// 2. `bridge-js.config.local.json` - public static func load(targetDirectory: URL) throws -> BridgeJSConfig { - // Define file paths in priority order: base first, then local overrides - let files = [ - targetDirectory.appendingPathComponent("bridge-js.config.json"), - targetDirectory.appendingPathComponent("bridge-js.config.local.json"), - ] - - var config = BridgeJSConfig() - - for file in files { - do { - if let loaded = try loadConfig(from: file) { - config = config.merging(overrides: loaded) - } - } catch { - throw BridgeJSCoreError("Failed to parse \(file.path): \(error)") - } - } - - return config - } - - /// Load a config file from the given URL if it exists, otherwise return nil - private static func loadConfig(from url: URL) throws -> BridgeJSConfig? { - guard FileManager.default.fileExists(atPath: url.path) else { - return nil - } - let data = try Data(contentsOf: url) - return try JSONDecoder().decode(BridgeJSConfig.self, from: data) - } - - /// Merge the current configuration with the overrides. - func merging(overrides: BridgeJSConfig) -> BridgeJSConfig { - return BridgeJSConfig( - tools: (tools ?? [:]).merging(overrides.tools ?? [:], uniquingKeysWith: { $1 }) - ) - } -} diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/BridgeJSCoreError.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/BridgeJSCoreError.swift deleted file mode 100644 index 9cbec438e..000000000 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/BridgeJSCoreError.swift +++ /dev/null @@ -1,7 +0,0 @@ -public struct BridgeJSCoreError: Swift.Error, CustomStringConvertible { - public let description: String - - public init(_ message: String) { - self.description = message - } -} diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift new file mode 100644 index 000000000..cbec4ba31 --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift @@ -0,0 +1,186 @@ +import SwiftBasicFormat +import SwiftSyntax +import SwiftSyntaxBuilder +#if canImport(BridgeJSSkeleton) +import BridgeJSSkeleton +#endif +#if canImport(BridgeJSUtilities) +import BridgeJSUtilities +#endif + +public struct ClosureCodegen { + public init() {} + + private func swiftClosureType(for signature: ClosureSignature) -> String { + let closureParams = signature.parameters.map { "\($0.swiftType)" }.joined(separator: ", ") + let swiftEffects = (signature.isAsync ? " async" : "") + (signature.isThrows ? " throws" : "") + let swiftReturnType = signature.returnType.swiftType + return "(\(closureParams))\(swiftEffects) -> \(swiftReturnType)" + } + + func renderClosureHelpers(_ signature: ClosureSignature) throws -> [DeclSyntax] { + let mangledName = signature.mangleName + let helperName = "_BJS_Closure_\(mangledName)" + let swiftClosureType = swiftClosureType(for: signature) + + let externName = "invoke_js_callback_\(signature.moduleName)_\(mangledName)" + + // Use CallJSEmission to generate the callback invocation + let builder = ImportTS.CallJSEmission( + moduleName: "bjs", + abiName: externName, + context: .exportSwift + ) + + // Lower the callback parameter + try builder.lowerParameter(param: Parameter(label: nil, name: "callback", type: .jsObject(nil))) + + // Lower each closure parameter + for (index, paramType) in signature.parameters.enumerated() { + try builder.lowerParameter(param: Parameter(label: nil, name: "param\(index)", type: paramType)) + } + + // Generate the call and return value lifting + try builder.call(returnType: signature.returnType) + try builder.liftReturnValue(returnType: signature.returnType) + + // Generate extern declaration using CallJSEmission + let externDecl = builder.renderImportDecl() + + let makeClosureExternDecl: DeclSyntax = """ + #if arch(wasm32) + @_extern(wasm, module: "bjs", name: "make_swift_closure_\(raw: signature.moduleName)_\(raw: signature.mangleName)") + fileprivate func make_swift_closure_\(raw: signature.moduleName)_\(raw: signature.mangleName)(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 + #else + fileprivate func make_swift_closure_\(raw: signature.moduleName)_\(raw: signature.mangleName)(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif + """ + + let helperEnumDeclPrinter = CodeFragmentPrinter() + helperEnumDeclPrinter.write("private enum \(helperName) {") + helperEnumDeclPrinter.indent { + helperEnumDeclPrinter.write("static func bridgeJSLift(_ callbackId: Int32) -> \(swiftClosureType) {") + helperEnumDeclPrinter.indent { + helperEnumDeclPrinter.write("let callback = JSObject.bridgeJSLiftParameter(callbackId)") + let parameters: String + if signature.parameters.isEmpty { + parameters = "" + } else if signature.parameters.count == 1 { + parameters = " param0" + } else { + parameters = + " (" + + signature.parameters.enumerated().map { index, _ in + "param\(index)" + }.joined(separator: ", ") + ")" + } + helperEnumDeclPrinter.write("return { [callback]\(parameters) in") + helperEnumDeclPrinter.indent { + SwiftCodePattern.buildWasmConditionalCompilation( + printer: helperEnumDeclPrinter, + wasmBody: { printer in + printer.write(lines: builder.body.lines) + } + ) + } + helperEnumDeclPrinter.write("}") + + } + helperEnumDeclPrinter.write("}") + } + helperEnumDeclPrinter.write("}") + + let helperEnumDecl: DeclSyntax = "\(raw: helperEnumDeclPrinter.lines.joined(separator: "\n"))" + + let typedClosureExtension: DeclSyntax = """ + extension JSTypedClosure where Signature == \(raw: swiftClosureType) { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping \(raw: swiftClosureType)) { + self.init( + makeClosure: make_swift_closure_\(raw: signature.moduleName)_\(raw: signature.mangleName), + body: body, + fileID: fileID, + line: line + ) + } + } + """ + + return [ + externDecl, makeClosureExternDecl, helperEnumDecl, typedClosureExtension, + ] + } + + func renderClosureInvokeHandler(_ signature: ClosureSignature) throws -> DeclSyntax { + let swiftClosureType = swiftClosureType(for: signature) + let boxType = "_BridgeJSTypedClosureBox<\(swiftClosureType)>" + let abiName = "invoke_swift_closure_\(signature.moduleName)_\(signature.mangleName)" + + // Build ABI parameters directly with WasmCoreType (no string conversion needed) + var abiParams: [(name: String, type: WasmCoreType)] = [("boxPtr", .pointer)] + var liftedParams: [String] = [] + + for (index, paramType) in signature.parameters.enumerated() { + let paramName = "param\(index)" + let liftInfo = try paramType.liftParameterInfo() + + for (argName, wasmType) in liftInfo.parameters { + let fullName = + liftInfo.parameters.count > 1 ? "\(paramName)\(argName.capitalizedFirstLetter)" : paramName + abiParams.append((fullName, wasmType)) + } + + let argNames = liftInfo.parameters.map { (argName, _) in + liftInfo.parameters.count > 1 ? "\(paramName)\(argName.capitalizedFirstLetter)" : paramName + } + liftedParams.append("\(paramType.swiftType).bridgeJSLiftParameter(\(argNames.joined(separator: ", ")))") + } + + let closureCallExpr = ExprSyntax("closure(\(raw: liftedParams.joined(separator: ", ")))") + + let abiReturnWasmType = try signature.returnType.loweringReturnInfo().returnType + + // Build signature using SwiftSignatureBuilder + let funcSignature = SwiftSignatureBuilder.buildABIFunctionSignature( + abiParameters: abiParams, + returnType: abiReturnWasmType + ) + + // Build function declaration using helper + let funcDecl = SwiftCodePattern.buildExposedFunctionDecl( + abiName: abiName, + signature: funcSignature + ) { printer in + printer.write("let closure = Unmanaged<\(boxType)>.fromOpaque(boxPtr).takeUnretainedValue().closure") + if signature.returnType == .void { + printer.write(closureCallExpr.description) + } else { + printer.write("let result = \(closureCallExpr)") + printer.write("return result.bridgeJSLowerReturn()") + } + } + + return DeclSyntax(funcDecl) + } + + public func renderSupport(for skeleton: BridgeJSSkeleton) throws -> String? { + let collector = ClosureSignatureCollectorVisitor() + var walker = BridgeTypeWalker(visitor: collector) + walker.walk(skeleton) + let closureSignatures = walker.visitor.signatures + + guard !closureSignatures.isEmpty else { return nil } + + var decls: [DeclSyntax] = [] + for signature in closureSignatures.sorted(by: { $0.mangleName < $1.mangleName }) { + decls.append(contentsOf: try renderClosureHelpers(signature)) + decls.append(try renderClosureInvokeHandler(signature)) + } + + return withSpan("Format Closure Glue") { + let format = BasicFormat() + return decls.map { $0.formatted(using: format).description }.joined(separator: "\n\n") + } + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/DiagnosticError.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/DiagnosticError.swift deleted file mode 100644 index 2688f8da2..000000000 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/DiagnosticError.swift +++ /dev/null @@ -1,23 +0,0 @@ -import SwiftSyntax - -struct DiagnosticError: Error { - let node: Syntax - let message: String - let hint: String? - - init(node: some SyntaxProtocol, message: String, hint: String? = nil) { - self.node = Syntax(node) - self.message = message - self.hint = hint - } - - func formattedDescription(fileName: String) -> String { - let locationConverter = SourceLocationConverter(fileName: fileName, tree: node.root) - let location = locationConverter.location(for: node.position) - var description = "\(fileName):\(location.line):\(location.column): error: \(message)" - if let hint { - description += "\nHint: \(hint)" - } - return description - } -} diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index e928011a5..207f6ee69 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -4,6 +4,9 @@ import SwiftSyntaxBuilder #if canImport(BridgeJSSkeleton) import BridgeJSSkeleton #endif +#if canImport(BridgeJSUtilities) +import BridgeJSUtilities +#endif /// Exports Swift functions and classes to JavaScript /// @@ -17,342 +20,88 @@ import BridgeJSSkeleton public class ExportSwift { let progress: ProgressReporting let moduleName: String + private let exposeToGlobal: Bool + private var skeleton: ExportedSkeleton + private var sourceFiles: [(sourceFile: SourceFileSyntax, inputFilePath: String)] = [] - private var exportedFunctions: [ExportedFunction] = [] - private var exportedClasses: [ExportedClass] = [] - private var typeDeclResolver: TypeDeclResolver = TypeDeclResolver() - - public init(progress: ProgressReporting, moduleName: String) { + public init(progress: ProgressReporting, moduleName: String, skeleton: ExportedSkeleton) { self.progress = progress self.moduleName = moduleName - } - - /// Processes a Swift source file to find declarations marked with @JS - /// - /// - Parameters: - /// - sourceFile: The parsed Swift source file to process - /// - inputFilePath: The file path for error reporting - public func addSourceFile(_ sourceFile: SourceFileSyntax, _ inputFilePath: String) throws { - progress.print("Processing \(inputFilePath)") - typeDeclResolver.addSourceFile(sourceFile) - - let errors = try parseSingleFile(sourceFile) - if errors.count > 0 { - throw BridgeJSCoreError( - errors.map { $0.formattedDescription(fileName: inputFilePath) } - .joined(separator: "\n") - ) - } + self.exposeToGlobal = skeleton.exposeToGlobal + self.skeleton = skeleton } /// Finalizes the export process and generates the bridge code /// + /// - Parameters: + /// - exposeToGlobal: Whether to expose exported APIs to the global namespace (default: false) /// - Returns: A tuple containing the generated Swift code and a skeleton /// describing the exported APIs - public func finalize() throws -> (outputSwift: String, outputSkeleton: ExportedSkeleton)? { - guard let outputSwift = renderSwiftGlue() else { + public func finalize() throws -> String? { + guard let outputSwift = try renderSwiftGlue() else { return nil } - return ( - outputSwift: outputSwift, - outputSkeleton: ExportedSkeleton( - moduleName: moduleName, - functions: exportedFunctions, - classes: exportedClasses - ) - ) + return outputSwift } - fileprivate final class APICollector: SyntaxAnyVisitor { - var exportedFunctions: [ExportedFunction] = [] - /// The names of the exported classes, in the order they were written in the source file - var exportedClassNames: [String] = [] - var exportedClassByName: [String: ExportedClass] = [:] - var errors: [DiagnosticError] = [] - - enum State { - case topLevel - case classBody(name: String) - } - - struct StateStack { - private var states: [State] - var current: State { - return states.last! - } - - init(_ initialState: State) { - self.states = [initialState] - } - mutating func push(state: State) { - states.append(state) - } + func renderSwiftGlue() throws -> String? { + var decls: [DeclSyntax] = [] - mutating func pop() { - _ = states.removeLast() + try withSpan("Render Protocols") { [self] in + let protocolCodegen = ProtocolCodegen() + for proto in skeleton.protocols { + decls.append(contentsOf: try protocolCodegen.renderProtocolWrapper(proto, moduleName: moduleName)) } } - var stateStack: StateStack = StateStack(.topLevel) - var state: State { - return stateStack.current - } - let parent: ExportSwift - - init(parent: ExportSwift) { - self.parent = parent - super.init(viewMode: .sourceAccurate) - } - - private func diagnose(node: some SyntaxProtocol, message: String, hint: String? = nil) { - errors.append(DiagnosticError(node: node, message: message, hint: hint)) - } - - private func diagnoseUnsupportedType(node: some SyntaxProtocol, type: String) { - diagnose( - node: node, - message: "Unsupported type: \(type)", - hint: "Only primitive types and types defined in the same module are allowed" - ) - } - - override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind { - switch state { - case .topLevel: - if let exportedFunction = visitFunction(node: node) { - exportedFunctions.append(exportedFunction) - } - return .skipChildren - case .classBody(let name): - if let exportedFunction = visitFunction(node: node) { - exportedClassByName[name]?.methods.append(exportedFunction) + try withSpan("Render Enums") { [self] in + let enumCodegen = EnumCodegen() + for enumDef in skeleton.enums { + if let enumHelpers = enumCodegen.renderEnumHelpers(enumDef) { + decls.append(enumHelpers) } - return .skipChildren - } - } - private func visitFunction(node: FunctionDeclSyntax) -> ExportedFunction? { - guard let jsAttribute = node.attributes.firstJSAttribute else { - return nil - } - - let name = node.name.text - let namespace = extractNamespace(from: jsAttribute) - - if namespace != nil, case .classBody = state { - diagnose( - node: jsAttribute, - message: "Namespace is only needed in top-level declaration", - hint: "Remove the namespace from @JS attribute or move this function to top-level" - ) - } - - var parameters: [Parameter] = [] - for param in node.signature.parameterClause.parameters { - guard let type = self.parent.lookupType(for: param.type) else { - diagnoseUnsupportedType(node: param.type, type: param.type.trimmedDescription) - continue - } - let name = param.secondName?.text ?? param.firstName.text - let label = param.firstName.text - parameters.append(Parameter(label: label, name: name, type: type)) - } - let returnType: BridgeType - if let returnClause = node.signature.returnClause { - guard let type = self.parent.lookupType(for: returnClause.type) else { - diagnoseUnsupportedType(node: returnClause.type, type: returnClause.type.trimmedDescription) - return nil + for staticMethod in enumDef.staticMethods { + decls.append(try renderSingleExportedFunction(function: staticMethod)) } - returnType = type - } else { - returnType = .void - } - - let abiName: String - switch state { - case .topLevel: - abiName = "bjs_\(name)" - case .classBody(let className): - abiName = "bjs_\(className)_\(name)" - } - - guard let effects = collectEffects(signature: node.signature) else { - return nil - } - - return ExportedFunction( - name: name, - abiName: abiName, - parameters: parameters, - returnType: returnType, - effects: effects, - namespace: namespace - ) - } - private func collectEffects(signature: FunctionSignatureSyntax) -> Effects? { - let isAsync = signature.effectSpecifiers?.asyncSpecifier != nil - var isThrows = false - if let throwsClause: ThrowsClauseSyntax = signature.effectSpecifiers?.throwsClause { - // Limit the thrown type to JSException for now - guard let thrownType = throwsClause.type else { - diagnose( - node: throwsClause, - message: "Thrown type is not specified, only JSException is supported for now" - ) - return nil - } - guard thrownType.trimmedDescription == "JSException" else { - diagnose( - node: throwsClause, - message: "Only JSException is supported for thrown type, got \(thrownType.trimmedDescription)" + for staticProperty in enumDef.staticProperties { + decls.append( + contentsOf: try renderSingleExportedProperty( + property: staticProperty, + context: .enumStatic(enumDef: enumDef) + ) ) - return nil } - isThrows = true - } - return Effects(isAsync: isAsync, isThrows: isThrows) - } - - private func extractNamespace( - from jsAttribute: AttributeSyntax - ) -> [String]? { - guard let arguments = jsAttribute.arguments?.as(LabeledExprListSyntax.self) else { - return nil - } - - guard let namespaceArg = arguments.first(where: { $0.label?.text == "namespace" }), - let stringLiteral = namespaceArg.expression.as(StringLiteralExprSyntax.self), - let namespaceString = stringLiteral.segments.first?.as(StringSegmentSyntax.self)?.content.text - else { - return nil } - - return namespaceString.split(separator: ".").map(String.init) } - override func visit(_ node: InitializerDeclSyntax) -> SyntaxVisitorContinueKind { - guard node.attributes.hasJSAttribute() else { return .skipChildren } - guard case .classBody(let name) = state else { - diagnose(node: node, message: "@JS init must be inside a @JS class") - return .skipChildren - } - - if let jsAttribute = node.attributes.firstJSAttribute, - extractNamespace(from: jsAttribute) != nil - { - diagnose( - node: jsAttribute, - message: "Namespace is not supported for initializer declarations", - hint: "Remove the namespace from @JS attribute" - ) - } - - var parameters: [Parameter] = [] - for param in node.signature.parameterClause.parameters { - guard let type = self.parent.lookupType(for: param.type) else { - diagnoseUnsupportedType(node: param.type, type: param.type.trimmedDescription) - continue - } - let name = param.secondName?.text ?? param.firstName.text - let label = param.firstName.text - parameters.append(Parameter(label: label, name: name, type: type)) + try withSpan("Render Structs") { [self] in + let structCodegen = StructCodegen() + for structDef in skeleton.structs { + decls.append(contentsOf: structCodegen.renderStructHelpers(structDef)) + decls.append(contentsOf: try renderSingleExportedStruct(struct: structDef)) } - guard let effects = collectEffects(signature: node.signature) else { - return .skipChildren + for function in skeleton.functions { + decls.append(try renderSingleExportedFunction(function: function)) } - - let constructor = ExportedConstructor( - abiName: "bjs_\(name)_init", - parameters: parameters, - effects: effects - ) - exportedClassByName[name]?.constructor = constructor - return .skipChildren - } - - override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { - let name = node.name.text - - stateStack.push(state: .classBody(name: name)) - - guard let jsAttribute = node.attributes.firstJSAttribute else { return .skipChildren } - - let namespace = extractNamespace(from: jsAttribute) - exportedClassByName[name] = ExportedClass( - name: name, - constructor: nil, - methods: [], - namespace: namespace - ) - exportedClassNames.append(name) - return .visitChildren - } - override func visitPost(_ node: ClassDeclSyntax) { - stateStack.pop() - } - } - - func parseSingleFile(_ sourceFile: SourceFileSyntax) throws -> [DiagnosticError] { - let collector = APICollector(parent: self) - collector.walk(sourceFile) - exportedFunctions.append(contentsOf: collector.exportedFunctions) - exportedClasses.append( - contentsOf: collector.exportedClassNames.map { - collector.exportedClassByName[$0]! + for klass in skeleton.classes { + decls.append(contentsOf: try renderSingleExportedClass(klass: klass)) } - ) - return collector.errors - } - - func lookupType(for type: TypeSyntax) -> BridgeType? { - if let primitive = BridgeType(swiftType: type.trimmedDescription) { - return primitive - } - guard let identifier = type.as(IdentifierTypeSyntax.self) else { - return nil - } - guard let typeDecl = typeDeclResolver.lookupType(for: identifier) else { - return nil - } - guard typeDecl.is(ClassDeclSyntax.self) || typeDecl.is(ActorDeclSyntax.self) else { - return nil - } - return .swiftHeapObject(typeDecl.name.text) - } - - static let prelude: DeclSyntax = """ - // 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(BridgeJS) import JavaScriptKit - """ - - func renderSwiftGlue() -> String? { - var decls: [DeclSyntax] = [] - guard exportedFunctions.count > 0 || exportedClasses.count > 0 else { - return nil - } - decls.append(Self.prelude) - for function in exportedFunctions { - decls.append(renderSingleExportedFunction(function: function)) } - for klass in exportedClasses { - decls.append(contentsOf: renderSingleExportedClass(klass: klass)) + return withSpan("Format Export Glue") { + return decls.map { $0.description }.joined(separator: "\n\n") } - let format = BasicFormat() - return decls.map { $0.formatted(using: format).description }.joined(separator: "\n\n") } class ExportedThunkBuilder { var body: [CodeBlockItemSyntax] = [] - var abiParameterForwardings: [LabeledExprSyntax] = [] + var liftedParameterExprs: [ExprSyntax] = [] + var parameters: [Parameter] = [] var abiParameterSignatures: [(name: String, type: WasmCoreType)] = [] var abiReturnType: WasmCoreType? + var externDecls: [DeclSyntax] = [] let effects: Effects init(effects: Effects) { @@ -368,90 +117,79 @@ public class ExportSwift { self.body.append(item) } - func liftParameter(param: Parameter) { + func liftParameter(param: Parameter) throws { + parameters.append(param) + let liftingInfo = try param.type.liftParameterInfo() + let argumentsToLift: [String] + if liftingInfo.parameters.count == 1 { + argumentsToLift = [param.name] + } else { + argumentsToLift = liftingInfo.parameters.map { (name, _) in param.name + name.capitalizedFirstLetter } + } + + let typeNameForIntrinsic: String + let liftingExpr: ExprSyntax + switch param.type { - case .bool: - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("\(raw: param.name) == 1") - ) - ) - abiParameterSignatures.append((param.name, .i32)) - case .int: - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("\(raw: param.type.swiftType)(\(raw: param.name))") - ) - ) - abiParameterSignatures.append((param.name, .i32)) - case .float: - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("\(raw: param.name)") - ) - ) - abiParameterSignatures.append((param.name, .f32)) - case .double: - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("\(raw: param.name)") - ) - ) - abiParameterSignatures.append((param.name, .f64)) - case .string: - let bytesLabel = "\(param.name)Bytes" - let lengthLabel = "\(param.name)Len" - let prepare: CodeBlockItemSyntax = """ - let \(raw: param.name) = String(unsafeUninitializedCapacity: Int(\(raw: lengthLabel))) { b in - _swift_js_init_memory(\(raw: bytesLabel), b.baseAddress.unsafelyUnwrapped) - return Int(\(raw: lengthLabel)) - } - """ - append(prepare) - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("\(raw: param.name)") - ) - ) - abiParameterSignatures.append((bytesLabel, .i32)) - abiParameterSignatures.append((lengthLabel, .i32)) - case .jsObject(nil): - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("JSObject(id: UInt32(bitPattern: \(raw: param.name)))") - ) - ) - abiParameterSignatures.append((param.name, .i32)) - case .jsObject(let name): - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("\(raw: name)(takingThis: UInt32(bitPattern: \(raw: param.name)))") - ) + case .closure(let signature, _): + typeNameForIntrinsic = param.type.swiftType + liftingExpr = ExprSyntax("_BJS_Closure_\(raw: signature.mangleName).bridgeJSLift(\(raw: param.name))") + case .swiftStruct(let structName): + typeNameForIntrinsic = structName + liftingExpr = ExprSyntax("\(raw: structName).bridgeJSLiftParameter()") + case .array: + typeNameForIntrinsic = param.type.swiftType + liftingExpr = StackCodegen().liftExpression(for: param.type) + case .nullable(let wrappedType, let kind): + let optionalSwiftType: String + if case .null = kind { + optionalSwiftType = "Optional" + } else { + optionalSwiftType = "JSUndefinedOr" + } + typeNameForIntrinsic = "\(optionalSwiftType)<\(wrappedType.swiftType)>" + liftingExpr = ExprSyntax( + "\(raw: typeNameForIntrinsic).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" ) - abiParameterSignatures.append((param.name, .i32)) - case .swiftHeapObject: - // UnsafeMutableRawPointer is passed as an i32 pointer - let objectExpr: ExprSyntax = - "Unmanaged<\(raw: param.type.swiftType)>.fromOpaque(\(raw: param.name)).takeUnretainedValue()" - abiParameterForwardings.append( - LabeledExprSyntax(label: param.label, expression: objectExpr) + default: + typeNameForIntrinsic = param.type.swiftType + liftingExpr = ExprSyntax( + "\(raw: typeNameForIntrinsic).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" ) - abiParameterSignatures.append((param.name, .pointer)) - case .void: - break } + + liftedParameterExprs.append(liftingExpr) + for (name, type) in zip(argumentsToLift, liftingInfo.parameters.map { $0.type }) { + abiParameterSignatures.append((name, type)) + } + } + + private func protocolCastSuffix(for returnType: BridgeType) -> (prefix: String, suffix: String) { + switch returnType { + case .swiftProtocol: + return ("", " as! \(returnType.swiftType)") + case .nullable(let wrappedType, _): + if case .swiftProtocol = wrappedType { + return ("(", ").flatMap { $0 as? \(wrappedType.swiftType) }") + } + return ("", "") + default: + return ("", "") + } + } + + private func removeFirstLiftedParameter() -> (parameter: Parameter, expr: ExprSyntax) { + let parameter = parameters.removeFirst() + let expr = liftedParameterExprs.removeFirst() + return (parameter, expr) } private func renderCallStatement(callee: ExprSyntax, returnType: BridgeType) -> CodeBlockItemSyntax { + let labeledParams = zip(parameters, liftedParameterExprs).map { param, expr in + LabeledExprSyntax(label: param.label, expression: expr) + } var callExpr: ExprSyntax = - "\(raw: callee)(\(raw: abiParameterForwardings.map { $0.description }.joined(separator: ", ")))" + "\(raw: callee)(\(raw: labeledParams.map { $0.description }.joined(separator: ", ")))" if effects.isAsync { callExpr = ExprSyntax( AwaitExprSyntax(awaitKeyword: .keyword(.await).with(\.trailingTrivia, .space), expression: callExpr) @@ -470,58 +208,102 @@ public class ExportSwift { return CodeBlockItemSyntax(item: .init(StmtSyntax("return \(raw: callExpr).jsValue"))) } - let retMutability = returnType == .string ? "var" : "let" if returnType == .void { return CodeBlockItemSyntax(item: .init(ExpressionStmtSyntax(expression: callExpr))) } else { - return CodeBlockItemSyntax(item: .init(DeclSyntax("\(raw: retMutability) ret = \(raw: callExpr)"))) + let (prefix, suffix) = protocolCastSuffix(for: returnType) + return CodeBlockItemSyntax( + item: .init(DeclSyntax("let ret = \(raw: prefix)\(raw: callExpr)\(raw: suffix)")) + ) } } func call(name: String, returnType: BridgeType) { + generateParameterLifting() let item = renderCallStatement(callee: "\(raw: name)", returnType: returnType) append(item) } - func callMethod(klassName: String, methodName: String, returnType: BridgeType) { - let _selfParam = self.abiParameterForwardings.removeFirst() + func callStaticProperty(name: String, returnType: BridgeType) { + if returnType == .void { + append("\(raw: name)") + } else { + let (prefix, suffix) = protocolCastSuffix(for: returnType) + append("let ret = \(raw: prefix)\(raw: name)\(raw: suffix)") + } + } + + func callMethod(methodName: String, returnType: BridgeType) { + let (_, selfExpr) = removeFirstLiftedParameter() + generateParameterLifting() let item = renderCallStatement( - callee: "\(raw: _selfParam).\(raw: methodName)", + callee: "\(raw: selfExpr).\(raw: methodName)", returnType: returnType ) append(item) } - func lowerReturnValue(returnType: BridgeType) { + /// Generates intermediate variables for stack-using parameters if needed for LIFO compatibility + private func generateParameterLifting() { + let stackParamIndices = parameters.enumerated().compactMap { index, param -> Int? in + switch param.type { + case .swiftStruct, .nullable(.swiftStruct, _), + .associatedValueEnum, .nullable(.associatedValueEnum, _), + .array: + return index + default: + return nil + } + } + + guard stackParamIndices.count > 1 else { return } + + for index in stackParamIndices.reversed() { + let param = parameters[index] + let expr = liftedParameterExprs[index] + let varName = "_tmp_\(param.name)" + + append("let \(raw: varName) = \(expr)") + liftedParameterExprs[index] = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(varName))) + } + } + + func callPropertyGetter(propertyName: String, returnType: BridgeType) { + let (_, selfExpr) = removeFirstLiftedParameter() + if returnType == .void { + append("\(raw: selfExpr).\(raw: propertyName)") + } else { + let (prefix, suffix) = protocolCastSuffix(for: returnType) + append("let ret = \(raw: prefix)\(raw: selfExpr).\(raw: propertyName)\(raw: suffix)") + } + } + + func callPropertySetter(propertyName: String) { + let (_, selfExpr) = removeFirstLiftedParameter() + let (_, newValueExpr) = removeFirstLiftedParameter() + append("\(raw: selfExpr).\(raw: propertyName) = \(raw: newValueExpr)") + } + + func callStaticPropertySetter(klassName: String, propertyName: String) { + let (_, newValueExpr) = removeFirstLiftedParameter() + append("\(raw: klassName).\(raw: propertyName) = \(raw: newValueExpr)") + } + + func lowerReturnValue(returnType: BridgeType) throws { if effects.isAsync { // Async functions always return a Promise, which is a JSObject - _lowerReturnValue(returnType: .jsObject(nil)) + try _lowerReturnValue(returnType: .jsObject(nil)) } else { - _lowerReturnValue(returnType: returnType) + try _lowerReturnValue(returnType: returnType) } } - private func _lowerReturnValue(returnType: BridgeType) { - switch returnType { - case .void: - abiReturnType = nil - case .bool: - abiReturnType = .i32 - case .int: - abiReturnType = .i32 - case .float: - abiReturnType = .f32 - case .double: - abiReturnType = .f64 - case .string: - abiReturnType = nil - case .jsObject: - abiReturnType = .i32 - case .swiftHeapObject: - // UnsafeMutableRawPointer is returned as an i32 pointer - abiReturnType = .pointer + private func _lowerReturnValue(returnType: BridgeType) throws { + let loweringInfo = try returnType.loweringReturnInfo() + abiReturnType = loweringInfo.returnType + if returnType == .void { + return } - if effects.isAsync { // The return value of async function (T of `(...) async -> T`) is // handled by the JSPromise.async, so we don't need to do anything here. @@ -529,39 +311,15 @@ public class ExportSwift { } switch returnType { - case .void: break - case .int, .float, .double: - append("return \(raw: abiReturnType!.swiftType)(ret)") - case .bool: - append("return Int32(ret ? 1 : 0)") - case .string: - append( - """ - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - """ - ) - case .jsObject(nil): - append( - """ - return _swift_js_retain(Int32(bitPattern: ret.id)) - """ - ) - case .jsObject(_?): - append( - """ - return _swift_js_retain(Int32(bitPattern: ret.this.id)) - """ - ) - case .swiftHeapObject: - // Perform a manual retain on the object, which will be balanced by a - // release called via FinalizationRegistry - append( - """ - return Unmanaged.passRetained(ret).toOpaque() - """ - ) + case .closure(_, useJSTypedClosure: false): + append("return JSTypedClosure(ret).bridgeJSLowerReturn()") + case .array, .nullable(.array, _): + let stackCodegen = StackCodegen() + for stmt in stackCodegen.lowerStatements(for: returnType, accessor: "ret", varPrefix: "ret") { + append(stmt) + } + default: + append("return ret.bridgeJSLowerReturn()") } } @@ -569,10 +327,10 @@ public class ExportSwift { let body: CodeBlockItemListSyntax if effects.isAsync { body = """ - let ret = JSPromise.async { - \(CodeBlockItemListSyntax(self.body)) - }.jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) + let ret = JSPromise.async { + \(CodeBlockItemListSyntax(self.body)) + }.jsObject + return ret.bridgeJSLowerReturn() """ } else if effects.isThrows { body = """ @@ -595,53 +353,224 @@ public class ExportSwift { } else { body = CodeBlockItemListSyntax(self.body) } - return """ - @_expose(wasm, "\(raw: abiName)") - @_cdecl("\(raw: abiName)") - public func _\(raw: abiName)(\(raw: parameterSignature())) -> \(raw: returnSignature()) { - #if arch(wasm32) - \(body) - #else - fatalError("Only available on WebAssembly") - #endif - } - """ + // Build function signature using SwiftSignatureBuilder + let signature = SwiftSignatureBuilder.buildABIFunctionSignature( + abiParameters: abiParameterSignatures, + returnType: abiReturnType + ) + + // Build function declaration using helper function + let funcDecl = SwiftCodePattern.buildExposedFunctionDecl( + abiName: abiName, + signature: signature + ) { printer in + printer.write(multilineString: body.description) + } + + return DeclSyntax(funcDecl) } private func returnPlaceholderStmt() -> String { - switch abiReturnType { - case .i32: return "return 0" - case .i64: return "return 0" - case .f32: return "return 0.0" - case .f64: return "return 0.0" - case .pointer: return "return UnsafeMutableRawPointer(bitPattern: -1).unsafelyUnwrapped" - case .none: return "return" + return abiReturnType?.swiftReturnPlaceholderStmt ?? "return" + } + } + + /// Context for property rendering that determines call behavior and ABI generation + private enum PropertyRenderingContext { + case enumStatic(enumDef: ExportedEnum) + case classStatic(klass: ExportedClass) + case classInstance(klass: ExportedClass) + case structStatic(structDef: ExportedStruct) + + var isStatic: Bool { + switch self { + case .enumStatic, .classStatic, .structStatic: + return true + case .classInstance: + return false } } - func parameterSignature() -> String { - var nameAndType: [(name: String, abiType: String)] = [] - for (name, type) in abiParameterSignatures { - nameAndType.append((name, type.swiftType)) + var className: String { + switch self { + case .enumStatic(let enumDef): + return enumDef.name + case .classStatic(let klass), .classInstance(let klass): + return klass.name + case .structStatic(let structDef): + return structDef.name } - return nameAndType.map { "\($0.name): \($0.abiType)" }.joined(separator: ", ") } - func returnSignature() -> String { - return abiReturnType?.swiftType ?? "Void" + func callName(for property: ExportedProperty) -> String { + switch self { + case .enumStatic(let enumDef): + return property.callName(prefix: enumDef.swiftCallName) + case .classStatic, .classInstance: + return property.callName() + case .structStatic(let structDef): + return property.callName(prefix: structDef.swiftCallName) + } + } + } + + /// Renders getter and setter Swift thunk code for a property in any context + /// This unified function eliminates duplication between enum static, class static, and class instance property rendering + private func renderSingleExportedProperty( + property: ExportedProperty, + context: PropertyRenderingContext + ) throws -> [DeclSyntax] { + var decls: [DeclSyntax] = [] + + let callName = context.callName(for: property) + let className = context.className + let isStatic = context.isStatic + + let getterBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false, isStatic: isStatic)) + + if !isStatic { + try getterBuilder.liftParameter( + param: Parameter(label: nil, name: "_self", type: .swiftHeapObject(className)) + ) + } + + if isStatic { + getterBuilder.callStaticProperty(name: callName, returnType: property.type) + } else { + getterBuilder.callPropertyGetter(propertyName: callName, returnType: property.type) + } + + try getterBuilder.lowerReturnValue(returnType: property.type) + decls.append(getterBuilder.render(abiName: property.getterAbiName(className: className))) + + // Generate property setter if not readonly + if !property.isReadonly { + let setterBuilder = ExportedThunkBuilder( + effects: Effects(isAsync: false, isThrows: false, isStatic: isStatic) + ) + + // Lift parameters based on property type + if !isStatic { + // Instance properties need _self parameter + try setterBuilder.liftParameter( + param: Parameter(label: nil, name: "_self", type: .swiftHeapObject(className)) + ) + } + + try setterBuilder.liftParameter( + param: Parameter(label: "value", name: "value", type: property.type) + ) + + if isStatic { + let klassName = callName.components(separatedBy: ".").dropLast().joined(separator: ".") + setterBuilder.callStaticPropertySetter(klassName: klassName, propertyName: property.name) + } else { + setterBuilder.callPropertySetter(propertyName: callName) + } + + try setterBuilder.lowerReturnValue(returnType: .void) + decls.append(setterBuilder.render(abiName: property.setterAbiName(className: className))) } + + return decls } - func renderSingleExportedFunction(function: ExportedFunction) -> DeclSyntax { + func renderSingleExportedFunction(function: ExportedFunction) throws -> DeclSyntax { let builder = ExportedThunkBuilder(effects: function.effects) for param in function.parameters { - builder.liftParameter(param: param) + try builder.liftParameter(param: param) + } + + if function.effects.isStatic, let staticContext = function.staticContext { + let callName = "\(staticContextBaseName(staticContext)).\(function.name)" + builder.call(name: callName, returnType: function.returnType) + } else { + builder.call(name: function.name, returnType: function.returnType) } - builder.call(name: function.name, returnType: function.returnType) - builder.lowerReturnValue(returnType: function.returnType) + + try builder.lowerReturnValue(returnType: function.returnType) return builder.render(abiName: function.abiName) } + private func staticContextBaseName(_ staticContext: StaticContext) -> String { + switch staticContext { + case .className(let baseName), .enumName(let baseName), .structName(let baseName), + .namespaceEnum(let baseName): + return baseName + } + } + + private func renderSingleExportedConstructor( + constructor: ExportedConstructor, + callName: String, + returnType: BridgeType + ) throws -> DeclSyntax { + let builder = ExportedThunkBuilder(effects: constructor.effects) + for param in constructor.parameters { + try builder.liftParameter(param: param) + } + builder.call(name: callName, returnType: returnType) + try builder.lowerReturnValue(returnType: returnType) + return builder.render(abiName: constructor.abiName) + } + + private func renderSingleExportedMethod( + method: ExportedFunction, + ownerTypeName: String, + instanceSelfType: BridgeType + ) throws -> DeclSyntax { + let builder = ExportedThunkBuilder(effects: method.effects) + if !method.effects.isStatic { + try builder.liftParameter(param: Parameter(label: nil, name: "_self", type: instanceSelfType)) + } + for param in method.parameters { + try builder.liftParameter(param: param) + } + + if method.effects.isStatic { + builder.call(name: "\(ownerTypeName).\(method.name)", returnType: method.returnType) + } else { + builder.callMethod(methodName: method.name, returnType: method.returnType) + } + try builder.lowerReturnValue(returnType: method.returnType) + return builder.render(abiName: method.abiName) + } + + func renderSingleExportedStruct(struct structDef: ExportedStruct) throws -> [DeclSyntax] { + var decls: [DeclSyntax] = [] + + if let constructor = structDef.constructor { + decls.append( + try renderSingleExportedConstructor( + constructor: constructor, + callName: structDef.swiftCallName, + returnType: .swiftStruct(structDef.swiftCallName) + ) + ) + } + + for property in structDef.properties where property.isStatic { + decls.append( + contentsOf: try renderSingleExportedProperty( + property: property, + context: .structStatic(structDef: structDef) + ) + ) + } + + for method in structDef.methods { + decls.append( + try renderSingleExportedMethod( + method: method, + ownerTypeName: structDef.swiftCallName, + instanceSelfType: .swiftStruct(structDef.swiftCallName) + ) + ) + } + + return decls + } + /// # Example /// /// Given the following Swift code: @@ -689,48 +618,50 @@ public class ExportSwift { /// Unmanaged.fromOpaque(pointer).release() /// } /// ``` - func renderSingleExportedClass(klass: ExportedClass) -> [DeclSyntax] { + func renderSingleExportedClass(klass: ExportedClass) throws -> [DeclSyntax] { var decls: [DeclSyntax] = [] + if let constructor = klass.constructor { - let builder = ExportedThunkBuilder(effects: constructor.effects) - for param in constructor.parameters { - builder.liftParameter(param: param) - } - builder.call(name: klass.name, returnType: .swiftHeapObject(klass.name)) - builder.lowerReturnValue(returnType: .swiftHeapObject(klass.name)) - decls.append(builder.render(abiName: constructor.abiName)) + decls.append( + try renderSingleExportedConstructor( + constructor: constructor, + callName: klass.swiftCallName, + returnType: .swiftHeapObject(klass.name) + ) + ) } for method in klass.methods { - let builder = ExportedThunkBuilder(effects: method.effects) - builder.liftParameter( - param: Parameter(label: nil, name: "_self", type: .swiftHeapObject(klass.name)) - ) - for param in method.parameters { - builder.liftParameter(param: param) - } - builder.callMethod( - klassName: klass.name, - methodName: method.name, - returnType: method.returnType + decls.append( + try renderSingleExportedMethod( + method: method, + ownerTypeName: klass.swiftCallName, + instanceSelfType: .swiftHeapObject(klass.swiftCallName) + ) ) - builder.lowerReturnValue(returnType: method.returnType) - decls.append(builder.render(abiName: method.abiName)) + } + + // Generate property getters and setters + for property in klass.properties { + let context: PropertyRenderingContext = + property.isStatic ? .classStatic(klass: klass) : .classInstance(klass: klass) + decls.append(contentsOf: try renderSingleExportedProperty(property: property, context: context)) } do { - decls.append( - """ - @_expose(wasm, "bjs_\(raw: klass.name)_deinit") - @_cdecl("bjs_\(raw: klass.name)_deinit") - public func _bjs_\(raw: klass.name)_deinit(pointer: UnsafeMutableRawPointer) { - Unmanaged<\(raw: klass.name)>.fromOpaque(pointer).release() - } - """ - ) + let funcDecl = SwiftCodePattern.buildExposedFunctionDecl( + abiName: "bjs_\(klass.name)_deinit", + signature: SwiftSignatureBuilder.buildABIFunctionSignature( + abiParameters: [("pointer", .pointer)], + returnType: nil + ) + ) { printer in + printer.write("Unmanaged<\(klass.swiftCallName)>.fromOpaque(pointer).release()") + } + decls.append(DeclSyntax(funcDecl)) } // Generate ConvertibleToJSValue extension - decls.append(renderConvertibleToJSValueExtension(klass: klass)) + decls.append(contentsOf: renderConvertibleToJSValueExtension(klass: klass)) return decls } @@ -742,63 +673,872 @@ public class ExportSwift { /// For a class named `Greeter`, this generates: /// /// ```swift - /// extension Greeter: ConvertibleToJSValue { + /// extension Greeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { /// var jsValue: JSValue { - /// @_extern(wasm, module: "MyModule", name: "bjs_Greeter_wrap") - /// func _bjs_Greeter_wrap(_: UnsafeMutableRawPointer) -> Int32 /// return JSObject(id: UInt32(bitPattern: _bjs_Greeter_wrap(Unmanaged.passRetained(self).toOpaque()))) /// } /// } + /// @_extern(wasm, module: "MyModule", name: "bjs_Greeter_wrap") + /// fileprivate func _bjs_Greeter_wrap(_: UnsafeMutableRawPointer) -> Int32 /// ``` - func renderConvertibleToJSValueExtension(klass: ExportedClass) -> DeclSyntax { + func renderConvertibleToJSValueExtension(klass: ExportedClass) -> [DeclSyntax] { let wrapFunctionName = "_bjs_\(klass.name)_wrap" let externFunctionName = "bjs_\(klass.name)_wrap" - return """ - extension \(raw: klass.name): ConvertibleToJSValue { - var jsValue: JSValue { - @_extern(wasm, module: "\(raw: moduleName)", name: "\(raw: externFunctionName)") - func \(raw: wrapFunctionName)(_: UnsafeMutableRawPointer) -> Int32 + // If the class has an explicit access control, we need to add it to the extension declaration. + let accessControl = klass.explicitAccessControl.map { "\($0) " } ?? "" + let extensionDecl: DeclSyntax = """ + extension \(raw: klass.swiftCallName): ConvertibleToJSValue, _BridgedSwiftHeapObject { + \(raw: accessControl)var jsValue: JSValue { return .object(JSObject(id: UInt32(bitPattern: \(raw: wrapFunctionName)(Unmanaged.passRetained(self).toOpaque())))) } } """ + // Build common function signature + let funcSignature = SwiftSignatureBuilder.buildABIFunctionSignature( + abiParameters: [("pointer", .pointer)], + returnType: .i32 + ) + + let externDeclPrinter = CodeFragmentPrinter() + SwiftCodePattern.buildWasmConditionalCompilationDecls( + printer: externDeclPrinter, + wasmDecl: { printer in + SwiftCodePattern.buildExternFunctionDecl( + printer: printer, + moduleName: moduleName, + abiName: externFunctionName, + functionName: wrapFunctionName, + signature: funcSignature + ) + }, + elseDecl: { printer in + printer.write( + multilineString: """ + fileprivate func \(wrapFunctionName)\(funcSignature) { + fatalError("Only available on WebAssembly") + } + """ + ) + } + ) + let externDecl: DeclSyntax = "\(raw: externDeclPrinter.lines.joined(separator: "\n"))" + return [extensionDecl, externDecl] } } -extension AttributeListSyntax { - fileprivate func hasJSAttribute() -> Bool { - firstJSAttribute != nil +// MARK: - StackCodegen + +/// Helper for stack-based lifting and lowering operations. +struct StackCodegen { + /// Generates an expression to lift a value from the parameter stack. + /// - Parameter type: The BridgeType to lift + /// - Returns: An ExprSyntax representing the lift expression + func liftExpression(for type: BridgeType) -> ExprSyntax { + switch type { + case .string, .int, .uint, .bool, .float, .double, + .jsObject(nil), .jsValue, .swiftStruct, .swiftHeapObject, .unsafePointer, + .swiftProtocol, .caseEnum, .associatedValueEnum, .rawValueEnum: + return "\(raw: type.swiftType).bridgeJSStackPop()" + case .jsObject(let className?): + return "\(raw: className)(unsafelyWrapping: JSObject.bridgeJSStackPop())" + case .nullable(let wrappedType, let kind): + return liftNullableExpression(wrappedType: wrappedType, kind: kind) + case .array(let elementType): + return liftArrayExpression(elementType: elementType) + case .dictionary(let valueType): + return liftDictionaryExpression(valueType: valueType) + case .closure: + return "JSObject.bridgeJSStackPop()" + case .void, .namespaceEnum: + return "()" + } } - fileprivate var firstJSAttribute: AttributeSyntax? { - first(where: { - $0.as(AttributeSyntax.self)?.attributeName.trimmedDescription == "JS" - })?.as(AttributeSyntax.self) + func liftArrayExpression(elementType: BridgeType) -> ExprSyntax { + switch elementType { + case .jsObject(let className?) where className != "JSObject": + return "[JSObject].bridgeJSStackPop().map { \(raw: className)(unsafelyWrapping: $0) }" + case .nullable, .closure: + return liftArrayExpressionInline(elementType: elementType) + case .void, .namespaceEnum: + fatalError("Invalid array element type: \(elementType)") + default: + return "[\(raw: elementType.swiftType)].bridgeJSStackPop()" + } } -} -extension BridgeType { - init?(swiftType: String) { - switch swiftType { - case "Int": - self = .int - case "Float": - self = .float - case "Double": - self = .double - case "String": - self = .string - case "Bool": - self = .bool - case "Void": - self = .void - case "JSObject": - self = .jsObject(nil) + private func liftArrayExpressionInline(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 + }() + """ + } + + func liftDictionaryExpression(valueType: BridgeType) -> ExprSyntax { + switch valueType { + case .jsObject(let className?) where className != "JSObject": + return """ + { + let __dict = [String: JSObject].bridgeJSStackPop() + return __dict.mapValues { \(raw: className)(unsafelyWrapping: $0) } + }() + """ + case .nullable, .closure: + return liftDictionaryExpressionInline(valueType: valueType) + case .void, .namespaceEnum: + fatalError("Invalid dictionary value type: \(valueType)") + default: + return "[String: \(raw: valueType.swiftType)].bridgeJSStackPop()" + } + } + + private func liftDictionaryExpressionInline(valueType: BridgeType) -> ExprSyntax { + let valueLift = liftExpression(for: valueType) + let swiftTypeName = valueType.swiftType + return """ + { + let __count = Int(_swift_js_pop_i32()) + var __result: [String: \(raw: swiftTypeName)] = [:] + __result.reserveCapacity(__count) + for _ in 0..<__count { + let __value = \(valueLift) + let __key = String.bridgeJSStackPop() + __result[__key] = __value + } + return __result + }() + """ + } + + private func liftNullableExpression(wrappedType: BridgeType, kind: JSOptionalKind) -> ExprSyntax { + let typeName = kind == .null ? "Optional" : "JSUndefinedOr" + switch wrappedType { + case .string, .int, .uint, .bool, .float, .double, .jsObject(nil), .jsValue, + .swiftStruct, .swiftHeapObject, .caseEnum, .associatedValueEnum, .rawValueEnum, + .array, .dictionary: + return "\(raw: typeName)<\(raw: wrappedType.swiftType)>.bridgeJSStackPop()" + case .jsObject(let className?): + return "\(raw: typeName).bridgeJSStackPop().map { \(raw: className)(unsafelyWrapping: $0) }" + case .nullable, .void, .namespaceEnum, .closure, .unsafePointer, .swiftProtocol: + fatalError("Invalid nullable wrapped type: \(wrappedType)") + } + } + + /// Generates statements to lower/push a value onto the stack. + /// - Parameters: + /// - type: The BridgeType to lower + /// - accessor: The expression to access the value (e.g., "self.name" or "paramName") + /// - varPrefix: A unique prefix for intermediate variables + /// - Returns: An array of CodeBlockItemSyntax representing the lowering statements + func lowerStatements( + for type: BridgeType, + accessor: String, + varPrefix: String + ) -> [CodeBlockItemSyntax] { + switch type { + case .string, .int, .uint, .bool, .float, .double, .jsValue, + .jsObject(nil), .swiftHeapObject, .unsafePointer, .closure, + .caseEnum, .rawValueEnum: + return ["\(raw: accessor).bridgeJSStackPush()"] + case .jsObject(_?): + return ["\(raw: accessor).jsObject.bridgeJSStackPush()"] + case .swiftProtocol: + return ["(\(raw: accessor) as! \(raw: type.swiftType)).bridgeJSStackPush()"] + case .associatedValueEnum, .swiftStruct: + return ["\(raw: accessor).bridgeJSStackPush()"] + case .nullable(let wrappedType, _): + return lowerOptionalStatements(wrappedType: wrappedType, accessor: accessor, varPrefix: varPrefix) + case .void, .namespaceEnum: + return [] + case .array(let elementType): + return lowerArrayStatements(elementType: elementType, accessor: accessor, varPrefix: varPrefix) + case .dictionary(let valueType): + return lowerDictionaryStatements(valueType: valueType, accessor: accessor, varPrefix: varPrefix) + } + } + + private func lowerArrayStatements( + elementType: BridgeType, + accessor: String, + varPrefix: String + ) -> [CodeBlockItemSyntax] { + switch elementType { + case .jsObject(let className?) where className != "JSObject": + return ["\(raw: accessor).map { $0.jsObject }.bridgeJSStackPush()"] + case .swiftProtocol: + return ["\(raw: accessor).map { $0 as! \(raw: elementType.swiftType) }.bridgeJSStackPush()"] + case .nullable, .closure: + return lowerArrayStatementsInline( + elementType: elementType, + accessor: accessor, + varPrefix: varPrefix + ) + case .void, .namespaceEnum: + fatalError("Invalid array element type: \(elementType)") + default: + return ["\(raw: accessor).bridgeJSStackPush()"] + } + } + + private func lowerArrayStatementsInline( + elementType: BridgeType, + accessor: String, + varPrefix: String + ) -> [CodeBlockItemSyntax] { + var statements: [String] = [] + let elementVarName = "__bjs_elem_\(varPrefix)" + statements.append("for \(elementVarName) in \(accessor) {") + + let elementStatements = lowerStatements( + for: elementType, + accessor: elementVarName, + varPrefix: "\(varPrefix)_elem" + ) + for stmt in elementStatements { + statements.append(stmt.description) + } + + statements.append("}") + statements.append("_swift_js_push_i32(Int32(\(accessor).count))") + let parsed: CodeBlockItemListSyntax = "\(raw: statements.joined(separator: "\n"))" + return Array(parsed) + } + + private func lowerDictionaryStatements( + valueType: BridgeType, + accessor: String, + varPrefix: String + ) -> [CodeBlockItemSyntax] { + switch valueType { + case .jsObject(let className?) where className != "JSObject": + return ["\(raw: accessor).mapValues { $0.jsObject }.bridgeJSStackPush()"] + case .swiftProtocol: + return ["\(raw: accessor).mapValues { $0 as! \(raw: valueType.swiftType) }.bridgeJSStackPush()"] + case .nullable, .closure: + return lowerDictionaryStatementsInline( + valueType: valueType, + accessor: accessor, + varPrefix: varPrefix + ) + case .void, .namespaceEnum: + fatalError("Invalid dictionary value type: \(valueType)") default: + return ["\(raw: accessor).bridgeJSStackPush()"] + } + } + + private func lowerDictionaryStatementsInline( + valueType: BridgeType, + accessor: String, + varPrefix: String + ) -> [CodeBlockItemSyntax] { + var statements: [CodeBlockItemSyntax] = [] + let pairVarName = "__bjs_kv_\(varPrefix)" + statements.append("for \(raw: pairVarName) in \(raw: accessor) {") + statements.append("let __bjs_key_\(raw: varPrefix) = \(raw: pairVarName).key") + statements.append("let __bjs_value_\(raw: varPrefix) = \(raw: pairVarName).value") + + let keyStatements = lowerStatements( + for: .string, + accessor: "__bjs_key_\(varPrefix)", + varPrefix: "\(varPrefix)_key" + ) + for stmt in keyStatements { + statements.append(stmt) + } + + let valueStatements = lowerStatements( + for: valueType, + accessor: "__bjs_value_\(varPrefix)", + varPrefix: "\(varPrefix)_value" + ) + for stmt in valueStatements { + statements.append(stmt) + } + + statements.append("}") + statements.append("_swift_js_push_i32(Int32(\(raw: accessor).count))") + return statements + } + + private func lowerOptionalStatements( + wrappedType: BridgeType, + accessor: String, + varPrefix: String + ) -> [CodeBlockItemSyntax] { + switch wrappedType { + case .array, .dictionary, .swiftStruct: + return ["\(raw: accessor).bridgeJSStackPush()"] + default: + break + } + + var statements: [String] = [] + statements.append("let __bjs_isSome_\(varPrefix) = \(accessor) != nil") + statements.append("if let __bjs_unwrapped_\(varPrefix) = \(accessor) {") + + let innerStatements = lowerUnwrappedOptionalStatements( + wrappedType: wrappedType, + unwrappedVar: "__bjs_unwrapped_\(varPrefix)" + ) + for stmt in innerStatements { + statements.append(stmt.description) + } + + statements.append("}") + statements.append("_swift_js_push_i32(__bjs_isSome_\(varPrefix) ? 1 : 0)") + let parsed: CodeBlockItemListSyntax = "\(raw: statements.joined(separator: "\n"))" + return Array(parsed) + } + + private func lowerUnwrappedOptionalStatements( + wrappedType: BridgeType, + unwrappedVar: String + ) -> [CodeBlockItemSyntax] { + switch wrappedType { + case .jsObject(_?): + return ["\(raw: unwrappedVar).jsObject.bridgeJSStackPush()"] + case .swiftProtocol: + return ["(\(raw: unwrappedVar) as! \(raw: wrappedType.swiftType)).bridgeJSStackPush()"] + case .string, .int, .uint, .bool, .float, .double, .jsValue, + .jsObject(nil), .swiftHeapObject, .unsafePointer, .closure, + .caseEnum, .rawValueEnum, .associatedValueEnum: + return ["\(raw: unwrappedVar).bridgeJSStackPush()"] + default: + return ["preconditionFailure(\"BridgeJS: unsupported optional wrapped type\")"] + } + } +} + +// MARK: - EnumCodegen + +struct EnumCodegen { + private let stackCodegen = StackCodegen() + + func renderEnumHelpers(_ enumDef: ExportedEnum) -> DeclSyntax? { + switch enumDef.enumType { + case .simple: + return renderCaseEnumHelpers(enumDef) + case .rawValue: + return renderRawValueEnumHelpers(enumDef) + case .associatedValue: + return renderAssociatedValueEnumHelpers(enumDef) + case .namespace: return nil } } + + private func renderCaseEnumHelpers(_ enumDef: ExportedEnum) -> DeclSyntax { + let printer = CodeFragmentPrinter() + printer.write("extension \(enumDef.swiftCallName): _BridgedSwiftCaseEnum {") + printer.indent { + printer.write( + multilineString: """ + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> \(enumDef.swiftCallName) { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> \(enumDef.swiftCallName) { + return \(enumDef.swiftCallName)(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + """ + ) + printer.nextLine() + + printer.write("private init?(bridgeJSRawValue: Int32) {") + printer.indent { + printer.write("switch bridgeJSRawValue {") + for (index, enumCase) in enumDef.cases.enumerated() { + printer.write("case \(index):") + printer.indent { + printer.write("self = .\(enumCase.name)") + } + } + printer.write("default:") + printer.indent { + printer.write("return nil") + } + printer.write("}") + } + printer.write("}") + printer.nextLine() + + printer.write("private var bridgeJSRawValue: Int32 {") + printer.indent { + printer.write("switch self {") + for (index, enumCase) in enumDef.cases.enumerated() { + printer.write("case .\(enumCase.name):") + printer.indent { + printer.write("return \(index)") + } + } + printer.write("}") + } + printer.write("}") + } + printer.write("}") + return "\(raw: printer.lines.joined(separator: "\n"))" + } + + private func renderRawValueEnumHelpers(_ enumDef: ExportedEnum) -> DeclSyntax { + let typeName = enumDef.swiftCallName + guard enumDef.rawType != nil else { + return """ + extension \(raw: typeName): _BridgedSwiftEnumNoPayload { + } + """ + } + // When rawType is present, conform to _BridgedSwiftRawValueEnum which provides + // default implementations for _BridgedSwiftStackType methods via protocol extension. + return """ + extension \(raw: typeName): _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { + } + """ + } + + private func renderAssociatedValueEnumHelpers(_ enumDef: ExportedEnum) -> DeclSyntax { + let typeName = enumDef.swiftCallName + let printer = CodeFragmentPrinter() + printer.write("extension \(typeName): _BridgedSwiftAssociatedValueEnum {") + printer.indent { + printer.write( + "@_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> \(typeName) {" + ) + printer.indent { + printer.write("switch caseId {") + generateStackLiftSwitchCases(printer: printer, enumDef: enumDef) + printer.write("default:") + printer.indent { + printer.write("fatalError(\"Unknown \(typeName) case ID: \\(caseId)\")") + } + printer.write("}") + } + printer.write("}") + printer.nextLine() + + printer.write("@_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 {") + printer.indent { + printer.write("switch self {") + generateReturnSwitchCases(printer: printer, enumDef: enumDef) + printer.write("}") + } + printer.write("}") + } + printer.write("}") + return "\(raw: printer.lines.joined(separator: "\n"))" + } + + private func generateStackLiftSwitchCases(printer: CodeFragmentPrinter, enumDef: ExportedEnum) { + for (caseIndex, enumCase) in enumDef.cases.enumerated() { + if enumCase.associatedValues.isEmpty { + printer.write("case \(caseIndex):") + printer.indent { + printer.write("return .\(enumCase.name)") + } + } else { + printer.write("case \(caseIndex):") + let argList = enumCase.associatedValues.map { associatedValue in + let labelPrefix: String + if let label = associatedValue.label { + labelPrefix = "\(label): " + } else { + labelPrefix = "" + } + let liftExpr = stackCodegen.liftExpression(for: associatedValue.type) + return "\(labelPrefix)\(liftExpr)" + } + printer.indent { + printer.write("return .\(enumCase.name)(\(argList.joined(separator: ", ")))") + } + } + } + } + + private func generatePayloadPushingCode( + printer: CodeFragmentPrinter, + associatedValues: [AssociatedValue] + ) { + for (index, associatedValue) in associatedValues.enumerated() { + let paramName = associatedValue.label ?? "param\(index)" + let statements = stackCodegen.lowerStatements( + for: associatedValue.type, + accessor: paramName, + varPrefix: paramName + ) + printer.write(multilineString: CodeBlockItemListSyntax(statements).description) + } + } + + private func generateReturnSwitchCases(printer: CodeFragmentPrinter, enumDef: ExportedEnum) { + for (caseIndex, enumCase) in enumDef.cases.enumerated() { + if enumCase.associatedValues.isEmpty { + printer.write("case .\(enumCase.name):") + printer.indent { + printer.write("return Int32(\(caseIndex))") + } + } else { + let pattern = enumCase.associatedValues.enumerated() + .map { index, associatedValue in "let \(associatedValue.label ?? "param\(index)")" } + .joined(separator: ", ") + printer.write("case .\(enumCase.name)(\(pattern)):") + printer.indent { + generatePayloadPushingCode(printer: printer, associatedValues: enumCase.associatedValues) + // Push tag AFTER payloads so it's popped first (LIFO) by the JS lift function. + // This ensures nested enum tags don't overwrite the outer tag. + printer.write("return Int32(\(caseIndex))") + } + } + } + } +} + +// MARK: - StructCodegen + +struct StructCodegen { + private let stackCodegen = StackCodegen() + + func renderStructHelpers(_ structDef: ExportedStruct) -> [DeclSyntax] { + let typeName = structDef.swiftCallName + + 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 printer = CodeFragmentPrinter() + printer.write("extension \(typeName): _BridgedSwiftStruct {") + printer.indent { + printer.write("@_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> \(typeName) {") + printer.indent { + printer.write(lines: generateStructLiftCode(structDef: structDef)) + } + printer.write("}") + printer.nextLine() + + printer.write("@_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() {") + printer.indent { + printer.write(lines: generateStructLowerCode(structDef: structDef)) + } + printer.write("}") + printer.nextLine() + + let accessControl = structDef.explicitAccessControl.map { "\($0) " } ?? "" + printer.write( + multilineString: """ + \(accessControl)init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = \(lowerFunctionName)(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + """ + ) + printer.nextLine() + + printer.write( + multilineString: """ + \(accessControl)func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: \(liftFunctionName)())) + } + """ + ) + } + printer.write("}") + + let bridgedStructExtension: DeclSyntax = "\(raw: printer.lines.joined(separator: "\n"))" + + let lowerExternDeclPrinter = CodeFragmentPrinter() + Self.renderStructExtern( + printer: lowerExternDeclPrinter, + externName: lowerExternName, + functionName: lowerFunctionName, + signature: SwiftSignatureBuilder.buildABIFunctionSignature( + abiParameters: [("objectId", .i32)], + returnType: .i32 + ) + ) + let liftExternDeclPrinter = CodeFragmentPrinter() + Self.renderStructExtern( + printer: liftExternDeclPrinter, + externName: liftExternName, + functionName: liftFunctionName, + signature: SwiftSignatureBuilder.buildABIFunctionSignature( + abiParameters: [], + returnType: .i32 + ) + ) + + return [ + bridgedStructExtension, "\(raw: lowerExternDeclPrinter.lines.joined(separator: "\n"))", + "\(raw: liftExternDeclPrinter.lines.joined(separator: "\n"))", + ] + } + + private static func renderStructExtern( + printer: CodeFragmentPrinter, + externName: String, + functionName: String, + signature: String + ) { + SwiftCodePattern.buildWasmConditionalCompilationDecls( + printer: printer, + wasmDecl: { printer in + SwiftCodePattern.buildExternFunctionDecl( + printer: printer, + moduleName: "bjs", + abiName: externName, + functionName: functionName, + signature: signature + ) + }, + elseDecl: { printer in + printer.write( + multilineString: """ + fileprivate func \(functionName)\(signature) { + fatalError("Only available on WebAssembly") + } + """ + ) + } + ) + } + + private func generateStructLiftCode(structDef: ExportedStruct) -> [String] { + var lines: [String] = [] + let instanceProps = structDef.properties.filter { !$0.isStatic } + + for property in instanceProps.reversed() { + let fieldName = property.name + let liftExpr = stackCodegen.liftExpression(for: property.type) + lines.append("let \(fieldName) = \(liftExpr)") + } + + let initArgs = instanceProps.map { "\($0.name): \($0.name)" }.joined(separator: ", ") + lines.append("return \(structDef.swiftCallName)(\(initArgs))") + + return lines + } + + private func generateStructLowerCode(structDef: ExportedStruct) -> [String] { + let printer = CodeFragmentPrinter() + let instanceProps = structDef.properties.filter { !$0.isStatic } + + for property in instanceProps { + let accessor = "self.\(property.name)" + let statements = stackCodegen.lowerStatements( + for: property.type, + accessor: accessor, + varPrefix: property.name + ) + printer.write(multilineString: CodeBlockItemListSyntax(statements).description) + } + + return printer.lines + } +} + +// MARK: - ProtocolCodegen + +struct ProtocolCodegen { + func renderProtocolWrapper(_ proto: ExportedProtocol, moduleName: String) throws -> [DeclSyntax] { + let wrapperName = "Any\(proto.name)" + let protocolName = proto.name + + var methodDecls: [CodeFragmentPrinter] = [] + var externDecls: [DeclSyntax] = [] + + for method in proto.methods { + let builder = ImportTS.CallJSEmission( + moduleName: moduleName, + abiName: "_extern_\(method.name)", + context: .exportSwift + ) + try builder.lowerParameter(param: Parameter(label: nil, name: "jsObject", type: .jsObject(nil))) + for param in method.parameters { + try builder.lowerParameter(param: param) + } + try builder.call(returnType: method.returnType) + try builder.liftReturnValue(returnType: method.returnType) + + // Build function signature using SwiftSignatureBuilder + let signature = SwiftSignatureBuilder.buildFunctionSignature( + parameters: method.parameters, + returnType: method.returnType, + effects: nil + ) + + // Build extern declaration using helper function + let externSignature = SwiftSignatureBuilder.buildABIFunctionSignature( + abiParameters: builder.abiParameterSignatures, + returnType: builder.abiReturnType + ) + let externDeclPrinter = CodeFragmentPrinter() + SwiftCodePattern.buildExternFunctionDecl( + printer: externDeclPrinter, + moduleName: moduleName, + abiName: method.abiName, + functionName: "_extern_\(method.name)", + signature: externSignature + ) + externDecls.append(DeclSyntax("\(raw: externDeclPrinter.lines.joined(separator: "\n"))")) + let methodImplPrinter = CodeFragmentPrinter() + methodImplPrinter.write("func \(method.name)\(signature) {") + methodImplPrinter.indent { + methodImplPrinter.write(lines: builder.body.lines) + } + methodImplPrinter.write("}") + methodDecls.append(methodImplPrinter) + } + + var propertyDecls: [CodeFragmentPrinter] = [] + + for property in proto.properties { + let propertyDeclPrinter = CodeFragmentPrinter() + let propertyExternDecls = try renderProtocolProperty( + printer: propertyDeclPrinter, + property: property, + protocolName: protocolName, + moduleName: moduleName + ) + propertyDecls.append(propertyDeclPrinter) + externDecls.append(contentsOf: propertyExternDecls) + } + + let structDeclPrinter = CodeFragmentPrinter() + structDeclPrinter.write("struct \(wrapperName): \(protocolName), _BridgedSwiftProtocolWrapper {") + structDeclPrinter.indent { + structDeclPrinter.write("let jsObject: JSObject") + structDeclPrinter.nextLine() + + for methodDecl in methodDecls { + structDeclPrinter.write(lines: methodDecl.lines) + structDeclPrinter.nextLine() + } + + for decl in propertyDecls { + structDeclPrinter.write(lines: decl.lines) + structDeclPrinter.nextLine() + } + structDeclPrinter.write( + multilineString: """ + static func bridgeJSLiftParameter(_ value: Int32) -> Self { + return \(wrapperName)(jsObject: JSObject(id: UInt32(bitPattern: value))) + } + """ + ) + } + structDeclPrinter.write("}") + + return ["\(raw: structDeclPrinter.lines.joined(separator: "\n"))"] + externDecls + } + + private func renderProtocolProperty( + printer: CodeFragmentPrinter, + property: ExportedProtocolProperty, + protocolName: String, + moduleName: String + ) throws -> [DeclSyntax] { + let getterAbiName = ABINameGenerator.generateABIName( + baseName: property.name, + operation: "get", + className: protocolName + ) + let setterAbiName = ABINameGenerator.generateABIName( + baseName: property.name, + operation: "set", + className: protocolName + ) + + let getterBuilder = ImportTS.CallJSEmission( + moduleName: moduleName, + abiName: getterAbiName, + context: .exportSwift + ) + try getterBuilder.lowerParameter(param: Parameter(label: nil, name: "jsObject", type: .jsObject(nil))) + try getterBuilder.call(returnType: property.type) + try getterBuilder.liftReturnValue(returnType: property.type) + + // Build getter extern declaration using helper function + let getterExternSignature = SwiftSignatureBuilder.buildABIFunctionSignature( + abiParameters: getterBuilder.abiParameterSignatures, + returnType: getterBuilder.abiReturnType + ) + let getterExternDeclPrinter = CodeFragmentPrinter() + SwiftCodePattern.buildExternFunctionDecl( + printer: getterExternDeclPrinter, + moduleName: moduleName, + abiName: getterAbiName, + functionName: getterAbiName, + signature: getterExternSignature + ) + let getterExternDecl = DeclSyntax("\(raw: getterExternDeclPrinter.lines.joined(separator: "\n"))") + var externDecls: [DeclSyntax] = [getterExternDecl] + + printer.write("var \(property.name): \(property.type.swiftType) {") + try printer.indent { + printer.write("get {") + printer.indent { + printer.write(lines: getterBuilder.body.lines) + } + printer.write("}") + + if property.isReadonly { return } + + let setterBuilder = ImportTS.CallJSEmission( + moduleName: moduleName, + abiName: setterAbiName, + context: .exportSwift + ) + try setterBuilder.lowerParameter(param: Parameter(label: nil, name: "jsObject", type: .jsObject(nil))) + try setterBuilder.lowerParameter(param: Parameter(label: nil, name: "newValue", type: property.type)) + try setterBuilder.call(returnType: .void) + + // Build setter extern declaration using helper function + let setterExternSignature = SwiftSignatureBuilder.buildABIFunctionSignature( + abiParameters: setterBuilder.abiParameterSignatures, + returnType: setterBuilder.abiReturnType + ) + let setterExternDeclPrinter = CodeFragmentPrinter() + SwiftCodePattern.buildExternFunctionDecl( + printer: setterExternDeclPrinter, + moduleName: moduleName, + abiName: setterAbiName, + functionName: setterAbiName, + signature: setterExternSignature + ) + let setterExternDecl = DeclSyntax("\(raw: setterExternDeclPrinter.lines.joined(separator: "\n"))") + externDecls.append(setterExternDecl) + + printer.write("set {") + printer.indent { + printer.write(lines: setterBuilder.body.lines) + } + printer.write("}") + } + printer.write("}") + + return externDecls + } } extension WasmCoreType { @@ -813,18 +1553,235 @@ 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 .jsValue: return "JSValue" 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 .nullable(let wrappedType, let kind): + return kind == .null ? "Optional<\(wrappedType.swiftType)>" : "JSUndefinedOr<\(wrappedType.swiftType)>" + case .array(let elementType): return "[\(elementType.swiftType)]" + case .dictionary(let valueType): return "[String: \(valueType.swiftType)]" + case .caseEnum(let name): return name + case .rawValueEnum(let name, _): return name + case .associatedValueEnum(let name): return name + case .swiftStruct(let name): return name + case .namespaceEnum(let name): return name + case .closure(let signature, let useJSTypedClosure): + let paramTypes = signature.parameters.map { $0.swiftType }.joined(separator: ", ") + let effectsStr = (signature.isAsync ? " async" : "") + (signature.isThrows ? " throws" : "") + let closureType = "(\(paramTypes))\(effectsStr) -> \(signature.returnType.swiftType)" + return useJSTypedClosure ? "JSTypedClosure<\(closureType)>" : closureType + } + } + + var isClosureType: Bool { + if case .closure = self { return true } + return false + } + + struct LiftingIntrinsicInfo: Sendable { + let parameters: [(name: String, type: WasmCoreType)] + + static let bool = LiftingIntrinsicInfo(parameters: [("value", .i32)]) + static let int = LiftingIntrinsicInfo(parameters: [("value", .i32)]) + static let float = LiftingIntrinsicInfo(parameters: [("value", .f32)]) + static let double = LiftingIntrinsicInfo(parameters: [("value", .f64)]) + static let string = LiftingIntrinsicInfo(parameters: [("bytes", .i32), ("length", .i32)]) + static let jsObject = LiftingIntrinsicInfo(parameters: [("value", .i32)]) + static let jsValue = LiftingIntrinsicInfo(parameters: [("kind", .i32), ("payload1", .i32), ("payload2", .f64)]) + static let swiftHeapObject = LiftingIntrinsicInfo(parameters: [("value", .pointer)]) + static let unsafePointer = LiftingIntrinsicInfo(parameters: [("pointer", .pointer)]) + static let void = LiftingIntrinsicInfo(parameters: []) + static let caseEnum = LiftingIntrinsicInfo(parameters: [("value", .i32)]) + static let associatedValueEnum = LiftingIntrinsicInfo(parameters: [ + ("caseId", .i32) + ]) + } + + func liftParameterInfo() throws -> LiftingIntrinsicInfo { + switch self { + case .bool: return .bool + case .int, .uint: return .int + case .float: return .float + case .double: return .double + case .string: return .string + case .jsObject: return .jsObject + case .jsValue: return .jsValue + case .swiftHeapObject: return .swiftHeapObject + case .unsafePointer: return .unsafePointer + case .swiftProtocol: return .jsObject + case .void: return .void + case .nullable(let wrappedType, _): + let wrappedInfo = try wrappedType.liftParameterInfo() + if wrappedInfo.parameters.isEmpty { + return LiftingIntrinsicInfo(parameters: []) + } + var optionalParams: [(name: String, type: WasmCoreType)] = [("isSome", .i32)] + optionalParams.append(contentsOf: wrappedInfo.parameters) + return LiftingIntrinsicInfo(parameters: optionalParams) + case .caseEnum: return .caseEnum + case .rawValueEnum(_, let rawType): + return rawType.liftingIntrinsicInfo + case .associatedValueEnum: + return .associatedValueEnum + case .swiftStruct: + return LiftingIntrinsicInfo(parameters: []) + case .namespaceEnum: + throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters") + case .closure: + return LiftingIntrinsicInfo(parameters: [("callbackId", .i32)]) + case .array, .dictionary: + return LiftingIntrinsicInfo(parameters: []) + } + } + + struct LoweringIntrinsicInfo: Sendable { + let returnType: WasmCoreType? + + static let bool = LoweringIntrinsicInfo(returnType: .i32) + static let int = LoweringIntrinsicInfo(returnType: .i32) + static let float = LoweringIntrinsicInfo(returnType: .f32) + static let double = LoweringIntrinsicInfo(returnType: .f64) + static let string = LoweringIntrinsicInfo(returnType: nil) + static let jsObject = LoweringIntrinsicInfo(returnType: .i32) + static let jsValue = LoweringIntrinsicInfo(returnType: nil) + static let swiftHeapObject = LoweringIntrinsicInfo(returnType: .pointer) + static let unsafePointer = LoweringIntrinsicInfo(returnType: .pointer) + static let void = LoweringIntrinsicInfo(returnType: nil) + static let caseEnum = LoweringIntrinsicInfo(returnType: .i32) + static let rawValueEnum = LoweringIntrinsicInfo(returnType: .i32) + static let associatedValueEnum = LoweringIntrinsicInfo(returnType: nil) + static let swiftStruct = LoweringIntrinsicInfo(returnType: nil) + static let optional = LoweringIntrinsicInfo(returnType: nil) + static let array = LoweringIntrinsicInfo(returnType: nil) + } + + func loweringReturnInfo() throws -> LoweringIntrinsicInfo { + switch self { + case .bool: return .bool + case .int, .uint: return .int + case .float: return .float + case .double: return .double + case .string: return .string + case .jsObject: return .jsObject + case .jsValue: return .jsValue + case .swiftHeapObject: return .swiftHeapObject + case .unsafePointer: return .unsafePointer + case .swiftProtocol: return .jsObject + case .void: return .void + case .nullable: return .optional + case .caseEnum: return .caseEnum + case .rawValueEnum(_, let rawType): + return rawType.loweringIntrinsicInfo + case .associatedValueEnum: + return .associatedValueEnum + case .swiftStruct: + return .swiftStruct + case .namespaceEnum: + throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters") + case .closure: + return .jsObject + case .array, .dictionary: + return .array + } + } +} + +extension SwiftEnumRawType { + var liftingIntrinsicInfo: BridgeType.LiftingIntrinsicInfo { + switch self { + case .bool: return .bool + case .int, .int32, .int64, .uint, .uint32, .uint64: return .int + case .float: return .float + case .double: return .double + case .string: return .string + } + } + + var loweringIntrinsicInfo: BridgeType.LoweringIntrinsicInfo { + switch self { + case .bool: return .bool + case .int, .int32, .int64, .uint, .uint32, .uint64: return .int + case .float: return .float + case .double: return .double + case .string: return .string + } + } +} + +extension DeclModifierSyntax { + var isAccessControl: Bool { + switch self.name.tokenKind { + case .keyword(.private), + .keyword(.fileprivate), + .keyword(.internal), + .keyword(.package), + .keyword(.public), + .keyword(.open): + return true + default: + return false + } + } + + var isAtLeastInternal: Bool { + switch self.name.tokenKind { + case .keyword(.private): false + case .keyword(.fileprivate): false + case .keyword(.internal): true + case .keyword(.package): true + case .keyword(.public): true + case .keyword(.open): true + default: false + } + } + + var isAtLeastPackage: Bool { + switch self.name.tokenKind { + case .keyword(.private): false + case .keyword(.fileprivate): false + case .keyword(.internal): true + case .keyword(.package): true + case .keyword(.public): true + case .keyword(.open): true + default: false + } + } +} + +extension WithModifiersSyntax { + var explicitAccessControl: DeclModifierSyntax? { + return self.modifiers.first { modifier in + modifier.isAccessControl } } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift index c7966a84e..8eead20b7 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift @@ -4,6 +4,9 @@ import SwiftSyntaxBuilder #if canImport(BridgeJSSkeleton) import BridgeJSSkeleton #endif +#if canImport(BridgeJSUtilities) +import BridgeJSUtilities +#endif /// Imports TypeScript declarations and generates Swift bridge code /// @@ -16,31 +19,36 @@ import BridgeJSSkeleton public struct ImportTS { public let progress: ProgressReporting public private(set) var skeleton: ImportedModuleSkeleton - private var moduleName: String { - skeleton.moduleName - } + private let moduleName: String - public init(progress: ProgressReporting, moduleName: String) { + public init(progress: ProgressReporting, moduleName: String, skeleton: ImportedModuleSkeleton) { self.progress = progress - self.skeleton = ImportedModuleSkeleton(moduleName: moduleName, children: []) - } - - /// Adds a skeleton to the importer's state - public mutating func addSkeleton(_ skeleton: ImportedFileSkeleton) { - self.skeleton.children.append(skeleton) + self.moduleName = moduleName + self.skeleton = skeleton } /// Finalizes the import process and generates Swift code public func finalize() throws -> String? { var decls: [DeclSyntax] = [] + for skeleton in self.skeleton.children { - for function in skeleton.functions { - let thunkDecls = try renderSwiftThunk(function, topLevelDecls: &decls) - decls.append(contentsOf: thunkDecls) + try withSpan("Render Global Getters") { + for getter in skeleton.globalGetters { + let getterDecls = try renderSwiftGlobalGetter(getter, topLevelDecls: &decls) + decls.append(contentsOf: getterDecls) + } } - for type in skeleton.types { - let typeDecls = try renderSwiftType(type, topLevelDecls: &decls) - decls.append(contentsOf: typeDecls) + try withSpan("Render Functions") { + for function in skeleton.functions { + let thunkDecls = try renderSwiftThunk(function, topLevelDecls: &decls) + decls.append(contentsOf: thunkDecls) + } + } + try withSpan("Render Types") { + for type in skeleton.types { + let typeDecls = try renderSwiftType(type, topLevelDecls: &decls) + decls.append(contentsOf: typeDecls) + } } } if decls.isEmpty { @@ -48,150 +56,160 @@ public struct ImportTS { return nil } - let format = BasicFormat() - let allDecls: [DeclSyntax] = [Self.prelude] + decls - return allDecls.map { $0.formatted(using: format).description }.joined(separator: "\n\n") + return withSpan("Format Import Glue") { + let format = BasicFormat() + return decls.map { $0.formatted(using: format).description }.joined(separator: "\n\n") + } } - class ImportedThunkBuilder { + func renderSwiftGlobalGetter( + _ getter: ImportedGetterSkeleton, + topLevelDecls: inout [DeclSyntax] + ) throws -> [DeclSyntax] { + let builder = CallJSEmission(moduleName: moduleName, abiName: getter.abiName(context: nil)) + try builder.call(returnType: getter.type) + try builder.liftReturnValue(returnType: getter.type) + topLevelDecls.append(builder.renderImportDecl()) + return [ + builder.renderThunkDecl( + name: "_$\(getter.name)_get", + parameters: [], + returnType: getter.type + ) + .with(\.leadingTrivia, Self.renderDocumentation(documentation: getter.documentation)) + ] + } + + class CallJSEmission { let abiName: String let moduleName: String + let context: BridgeContext - var body: [CodeBlockItemSyntax] = [] - var abiParameterForwardings: [LabeledExprSyntax] = [] + var body = CodeFragmentPrinter() + var abiParameterForwardings: [String] = [] var abiParameterSignatures: [(name: String, type: WasmCoreType)] = [] var abiReturnType: WasmCoreType? - - init(moduleName: String, abiName: String) { + // Track destructured variable names for multiple lowered parameters + var destructuredVarNames: [String] = [] + // Stack-lowered parameters should be evaluated in reverse order to match LIFO stacks + var stackLoweringStmts: [String] = [] + // Values to extend lifetime during call + var valuesToExtendLifetimeDuringCall: [String] = [] + + init(moduleName: String, abiName: String, context: BridgeContext = .importTS) { self.moduleName = moduleName self.abiName = abiName + self.context = context } func lowerParameter(param: Parameter) throws { + let loweringInfo = try param.type.loweringParameterInfo(context: context) + switch param.type { - case .bool: - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("Int32(\(raw: param.name) ? 1 : 0)") - ) - ) - abiParameterSignatures.append((param.name, .i32)) - case .int: - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("\(raw: param.name)") - ) - ) - abiParameterSignatures.append((param.name, .i32)) - case .float: - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("\(raw: param.name)") - ) - ) - abiParameterSignatures.append((param.name, .f32)) - case .double: - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("\(raw: param.name)") - ) - ) - abiParameterSignatures.append((param.name, .f64)) - case .string: - let stringIdName = "\(param.name)Id" - body.append( - """ - var \(raw: param.name) = \(raw: param.name) - - """ - ) - body.append( - """ - let \(raw: stringIdName) = \(raw: param.name).withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - """ - ) - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("\(raw: stringIdName)") - ) - ) - abiParameterSignatures.append((param.name, .i32)) - case .jsObject(_?): - abiParameterSignatures.append((param.name, .i32)) - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("Int32(bitPattern: \(raw: param.name).this.id)") - ) - ) - case .jsObject(nil): - abiParameterForwardings.append( - LabeledExprSyntax( - label: param.label, - expression: ExprSyntax("Int32(bitPattern: \(raw: param.name).id)") - ) - ) - abiParameterSignatures.append((param.name, .i32)) - case .swiftHeapObject(_): - throw BridgeJSCoreError("swiftHeapObject is not supported in imported signatures") - case .void: + case .closure(let signature, useJSTypedClosure: false): + let jsTypedClosureType = BridgeType.closure(signature, useJSTypedClosure: true).swiftType + body.write("let \(param.name) = \(jsTypedClosureType)(\(param.name))") + // The just created JSObject is not owned by the caller unlike those passed in parameters, + // so we need to extend its lifetime during the call to ensure the JSObject.id is valid. + valuesToExtendLifetimeDuringCall.append(param.name) + default: break } + let initializerExpr = ExprSyntax("\(raw: param.name).bridgeJSLowerParameter()") + + if loweringInfo.loweredParameters.isEmpty { + stackLoweringStmts.insert("let _ = \(initializerExpr)", at: 0) + return + } + + // Generate destructured variable names for all lowered parameters + let destructuredNames = loweringInfo.loweredParameters.map { + "\(param.name)\($0.name.capitalizedFirstLetter)" + } + + // Always add destructuring statement to body (unified for single and multiple) + let pattern: String + if destructuredNames.count == 1 { + pattern = destructuredNames[0] + } else { + pattern = "(" + destructuredNames.joined(separator: ", ") + ")" + } + + body.write("let \(pattern) = \(initializerExpr)") + destructuredVarNames.append(contentsOf: destructuredNames) + + // Add to signatures and forwardings (unified for both single and multiple) + for (index, (paramName, type)) in loweringInfo.loweredParameters.enumerated() { + // For single parameter, use param.name; for multiple, use constructed name + let abiParamName: String + if loweringInfo.loweredParameters.count == 1 { + abiParamName = param.name + } else { + abiParamName = "\(param.name)\(paramName.capitalizedFirstLetter)" + } + abiParameterSignatures.append((abiParamName, type)) + + // Always use destructured variable in call without labels + // Swift allows omitting labels when they match parameter names + abiParameterForwardings.append(destructuredNames[index]) + } } - func call(returnType: BridgeType) { - let call: ExprSyntax = - "\(raw: abiName)(\(raw: abiParameterForwardings.map { $0.description }.joined(separator: ", ")))" - if returnType == .void { - body.append("\(raw: call)") + func call(returnType: BridgeType) throws { + let liftingInfo: BridgeType.LiftingReturnInfo = try returnType.liftingReturnInfo(context: context) + for stmt in stackLoweringStmts { + body.write(stmt.description) + } + + let assign = + (returnType == .void || returnType.usesSideChannelForOptionalReturn() || liftingInfo.valueToLift == nil) + ? "" : "let ret = " + let callExpr = "\(abiName)(\(abiParameterForwardings.joined(separator: ", ")))" + + if !valuesToExtendLifetimeDuringCall.isEmpty { + body.write( + "\(assign)withExtendedLifetime((\(valuesToExtendLifetimeDuringCall.joined(separator: ", ")))) {" + ) + body.indent { + body.write(callExpr) + } + body.write("}") } else { - body.append("let ret = \(raw: call)") + body.write("\(assign)\(callExpr)") + } + + // Add exception check for ImportTS context + if context == .importTS { + body.write("if let error = _swift_js_take_exception() { throw error }") } - body.append("if let error = _swift_js_take_exception() { throw error }") } func liftReturnValue(returnType: BridgeType) throws { - switch returnType { - case .bool: - abiReturnType = .i32 - body.append("return ret == 1") - case .int: - abiReturnType = .i32 - body.append("return \(raw: returnType.swiftType)(ret)") - case .float: - abiReturnType = .f32 - body.append("return \(raw: returnType.swiftType)(ret)") - case .double: - abiReturnType = .f64 - body.append("return \(raw: returnType.swiftType)(ret)") - case .string: - abiReturnType = .i32 - body.append( - """ - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) + let liftingInfo = try returnType.liftingReturnInfo(context: context) + + if returnType == .void { + abiReturnType = nil + return + } + + if returnType.usesSideChannelForOptionalReturn() { + // Side channel returns: extern function returns Void, value is retrieved via side channel + abiReturnType = nil + body.write("return \(returnType.swiftType).bridgeJSLiftReturnFromSideChannel()") + } else { + abiReturnType = liftingInfo.valueToLift + let liftExpr: String + switch returnType { + case .closure(let signature, _): + liftExpr = "_BJS_Closure_\(signature.mangleName).bridgeJSLift(ret)" + default: + if liftingInfo.valueToLift != nil { + liftExpr = "\(returnType.swiftType).bridgeJSLiftReturn(ret)" + } else { + liftExpr = "\(returnType.swiftType).bridgeJSLiftReturn()" } - """ - ) - case .jsObject(let name): - abiReturnType = .i32 - if let name = name { - body.append("return \(raw: name)(takingThis: ret)") - } else { - body.append("return JSObject(id: UInt32(bitPattern: ret))") } - case .swiftHeapObject(_): - throw BridgeJSCoreError("swiftHeapObject is not supported in imported signatures") - case .void: - break + body.write("return \(liftExpr)") } } @@ -200,126 +218,110 @@ public struct ImportTS { preconditionFailure("assignThis can only be called with a jsObject return type") } abiReturnType = .i32 - body.append("self.this = JSObject(id: UInt32(bitPattern: ret))") + body.write("self.jsObject = JSObject(id: UInt32(bitPattern: ret))") } func renderImportDecl() -> DeclSyntax { - let baseDecl = FunctionDeclSyntax( - funcKeyword: .keyword(.func).with(\.trailingTrivia, .space), - name: .identifier(abiName), - signature: FunctionSignatureSyntax( - parameterClause: FunctionParameterClauseSyntax(parametersBuilder: { - for param in abiParameterSignatures { - FunctionParameterSyntax( - firstName: .wildcardToken().with(\.trailingTrivia, .space), - secondName: .identifier(param.name), - type: IdentifierTypeSyntax(name: .identifier(param.type.swiftType)) - ) - } - }), - returnClause: ReturnClauseSyntax( - arrow: .arrowToken(), - type: IdentifierTypeSyntax(name: .identifier(abiReturnType.map { $0.swiftType } ?? "Void")) + let signature = SwiftSignatureBuilder.buildABIFunctionSignature( + abiParameters: abiParameterSignatures, + returnType: abiReturnType + ) + + let printer = CodeFragmentPrinter() + SwiftCodePattern.buildWasmConditionalCompilationDecls( + printer: printer, + wasmDecl: { printer in + SwiftCodePattern.buildExternFunctionDecl( + printer: printer, + moduleName: moduleName, + abiName: abiName, + functionName: abiName, + signature: signature ) - ) + }, + elseDecl: { printer in + printer.write( + multilineString: """ + fileprivate func \(abiName)\(signature) { + fatalError("Only available on WebAssembly") + } + """ + ) + } ) - var externDecl = baseDecl - externDecl.attributes = AttributeListSyntax(itemsBuilder: { - "@_extern(wasm, module: \"\(raw: moduleName)\", name: \"\(raw: abiName)\")" - }).with(\.trailingTrivia, .newline) - var stubDecl = baseDecl - stubDecl.body = CodeBlockSyntax { - """ - fatalError("Only available on WebAssembly") - """ - } - return """ - #if arch(wasm32) - \(externDecl) - #else - \(stubDecl) - #endif - """ + return "\(raw: printer.lines.joined(separator: "\n"))" } func renderThunkDecl(name: String, parameters: [Parameter], returnType: BridgeType) -> DeclSyntax { - return DeclSyntax( - FunctionDeclSyntax( - name: .identifier(name), - signature: FunctionSignatureSyntax( - parameterClause: FunctionParameterClauseSyntax(parametersBuilder: { - for param in parameters { - FunctionParameterSyntax( - firstName: .wildcardToken(), - secondName: .identifier(param.name), - colon: .colonToken(), - type: IdentifierTypeSyntax(name: .identifier(param.type.swiftType)) - ) - } - }), - effectSpecifiers: ImportTS.buildFunctionEffect(throws: true, async: false), - returnClause: ReturnClauseSyntax( - arrow: .arrowToken(), - type: IdentifierTypeSyntax(name: .identifier(returnType.swiftType)) - ) - ), - body: CodeBlockSyntax { - self.renderImportDecl() - body - } - ) + let printer = CodeFragmentPrinter() + let effects = Effects(isAsync: false, isThrows: true) + let signature = SwiftSignatureBuilder.buildFunctionSignature( + parameters: parameters, + returnType: returnType, + effects: effects, + useWildcardLabels: true ) + printer.write("func \(name.backtickIfNeeded())\(signature) {") + printer.indent { + printer.write(lines: body.lines) + } + printer.write("}") + return "\(raw: printer.lines.joined(separator: "\n"))" } func renderConstructorDecl(parameters: [Parameter]) -> DeclSyntax { - return DeclSyntax( - InitializerDeclSyntax( - signature: FunctionSignatureSyntax( - parameterClause: FunctionParameterClauseSyntax( - parametersBuilder: { - for param in parameters { - FunctionParameterSyntax( - firstName: .wildcardToken(), - secondName: .identifier(param.name), - type: IdentifierTypeSyntax(name: .identifier(param.type.swiftType)) - ) - } - } - ), - effectSpecifiers: ImportTS.buildFunctionEffect(throws: true, async: false) - ), - bodyBuilder: { - self.renderImportDecl() - body - } - ) + let printer = CodeFragmentPrinter() + let effects = Effects(isAsync: false, isThrows: true) + let parameterClause = SwiftSignatureBuilder.buildParameterClause( + parameters: parameters, + useWildcardLabels: true ) + let effectSpecifiers = SwiftSignatureBuilder.buildEffectSpecifiers(effects: effects) + printer.write("init\(parameterClause)\(effectSpecifiers.map { " \($0)" } ?? "") {") + printer.indent { + printer.write(lines: body.lines) + } + printer.write("}") + return "\(raw: printer.lines.joined(separator: "\n"))" } } - static let prelude: DeclSyntax = """ - // 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`. + private static func thunkName(function: ImportedFunctionSkeleton) -> String { + "_$\(function.name)" + } + + private static func thunkName(type: ImportedTypeSkeleton, method: ImportedFunctionSkeleton) -> String { + "_$\(type.name)_\(method.name)" + } + + private static func thunkName(type: ImportedTypeSkeleton) -> String { + "_$\(type.name)_init" + } - @_spi(BridgeJS) import JavaScriptKit - """ + private static func thunkName( + type: ImportedTypeSkeleton, + propertyName: String, + operation: String + ) + -> String + { + "_$\(type.name)_\(propertyName)_\(operation)" + } func renderSwiftThunk( _ function: ImportedFunctionSkeleton, topLevelDecls: inout [DeclSyntax] ) throws -> [DeclSyntax] { - let builder = ImportedThunkBuilder(moduleName: moduleName, abiName: function.abiName(context: nil)) + let builder = CallJSEmission(moduleName: moduleName, abiName: function.abiName(context: nil)) for param in function.parameters { try builder.lowerParameter(param: param) } - builder.call(returnType: function.returnType) + try builder.call(returnType: function.returnType) try builder.liftReturnValue(returnType: function.returnType) + topLevelDecls.append(builder.renderImportDecl()) return [ builder.renderThunkDecl( - name: function.name, + name: Self.thunkName(function: function), parameters: function.parameters, returnType: function.returnType ) @@ -328,143 +330,126 @@ public struct ImportTS { } func renderSwiftType(_ type: ImportedTypeSkeleton, topLevelDecls: inout [DeclSyntax]) throws -> [DeclSyntax] { - let name = type.name + let selfParameter = Parameter(label: nil, name: "self", type: .jsObject(nil)) + var decls: [DeclSyntax] = [] func renderMethod(method: ImportedFunctionSkeleton) throws -> [DeclSyntax] { - let builder = ImportedThunkBuilder(moduleName: moduleName, abiName: method.abiName(context: type)) - try builder.lowerParameter(param: Parameter(label: nil, name: "self", type: .jsObject(name))) + let builder = CallJSEmission(moduleName: moduleName, abiName: method.abiName(context: type)) + try builder.lowerParameter(param: selfParameter) for param in method.parameters { try builder.lowerParameter(param: param) } - builder.call(returnType: method.returnType) + try builder.call(returnType: method.returnType) try builder.liftReturnValue(returnType: method.returnType) + topLevelDecls.append(builder.renderImportDecl()) return [ builder.renderThunkDecl( - name: method.name, + name: Self.thunkName(type: type, method: method), + parameters: [selfParameter] + method.parameters, + returnType: method.returnType + ) + ] + } + + func renderStaticMethod(method: ImportedFunctionSkeleton) throws -> [DeclSyntax] { + let abiName = method.abiName(context: type, operation: "static") + let builder = CallJSEmission(moduleName: moduleName, abiName: abiName) + for param in method.parameters { + try builder.lowerParameter(param: param) + } + try builder.call(returnType: method.returnType) + try builder.liftReturnValue(returnType: method.returnType) + topLevelDecls.append(builder.renderImportDecl()) + return [ + builder.renderThunkDecl( + name: Self.thunkName(type: type, method: method), parameters: method.parameters, returnType: method.returnType ) - .with(\.leadingTrivia, Self.renderDocumentation(documentation: method.documentation)) ] } func renderConstructorDecl(constructor: ImportedConstructorSkeleton) throws -> [DeclSyntax] { - let builder = ImportedThunkBuilder(moduleName: moduleName, abiName: constructor.abiName(context: type)) + let builder = CallJSEmission(moduleName: moduleName, abiName: constructor.abiName(context: type)) for param in constructor.parameters { try builder.lowerParameter(param: param) } - builder.call(returnType: .jsObject(name)) - builder.assignThis(returnType: .jsObject(name)) + try builder.call(returnType: .jsObject(nil)) + try builder.liftReturnValue(returnType: .jsObject(nil)) + topLevelDecls.append(builder.renderImportDecl()) return [ - builder.renderConstructorDecl(parameters: constructor.parameters) + builder.renderThunkDecl( + name: Self.thunkName(type: type), + parameters: constructor.parameters, + returnType: .jsObject(nil) + ) ] } - func renderGetterDecl(property: ImportedPropertySkeleton) throws -> AccessorDeclSyntax { - let builder = ImportedThunkBuilder( + func renderGetterDecl(getter: ImportedGetterSkeleton) throws -> DeclSyntax { + let builder = CallJSEmission( moduleName: moduleName, - abiName: property.getterAbiName(context: type) + abiName: getter.abiName(context: type) ) - try builder.lowerParameter(param: Parameter(label: nil, name: "self", type: .jsObject(name))) - builder.call(returnType: property.type) - try builder.liftReturnValue(returnType: property.type) - return AccessorDeclSyntax( - accessorSpecifier: .keyword(.get), - effectSpecifiers: Self.buildAccessorEffect(throws: true, async: false), - body: CodeBlockSyntax { - builder.renderImportDecl() - builder.body - } + try builder.lowerParameter(param: selfParameter) + try builder.call(returnType: getter.type) + try builder.liftReturnValue(returnType: getter.type) + topLevelDecls.append(builder.renderImportDecl()) + return DeclSyntax( + builder.renderThunkDecl( + name: Self.thunkName(type: type, propertyName: getter.name, operation: "get"), + parameters: [selfParameter], + returnType: getter.type + ) ) } - func renderSetterDecl(property: ImportedPropertySkeleton) throws -> DeclSyntax { - let builder = ImportedThunkBuilder( + func renderSetterDecl(setter: ImportedSetterSkeleton) throws -> DeclSyntax { + let builder = CallJSEmission( moduleName: moduleName, - abiName: property.setterAbiName(context: type) + abiName: setter.abiName(context: type) ) - let newValue = Parameter(label: nil, name: "newValue", type: property.type) - try builder.lowerParameter(param: Parameter(label: nil, name: "self", type: .jsObject(name))) + let newValue = Parameter(label: nil, name: "newValue", type: setter.type) + try builder.lowerParameter(param: selfParameter) try builder.lowerParameter(param: newValue) - builder.call(returnType: .void) + try builder.call(returnType: .void) + topLevelDecls.append(builder.renderImportDecl()) + // Use functionName if available (has lowercase first char), otherwise derive from name + let propertyNameForThunk: String + if let functionName = setter.functionName, functionName.hasSuffix("_set") { + // Extract base name from functionName (e.g., "any_set" -> "any") + propertyNameForThunk = String(functionName.dropLast(4)) + } else { + // Lowercase first character of property name for thunk + propertyNameForThunk = setter.name.prefix(1).lowercased() + setter.name.dropFirst() + } return builder.renderThunkDecl( - name: "set\(property.name.capitalizedFirstLetter())", - parameters: [newValue], + name: Self.thunkName(type: type, propertyName: propertyNameForThunk, operation: "set"), + parameters: [selfParameter, newValue], returnType: .void ) } - - func renderPropertyDecl(property: ImportedPropertySkeleton) throws -> [DeclSyntax] { - let accessorDecls: [AccessorDeclSyntax] = [try renderGetterDecl(property: property)] - var decls: [DeclSyntax] = [ - DeclSyntax( - VariableDeclSyntax( - leadingTrivia: Self.renderDocumentation(documentation: property.documentation), - bindingSpecifier: .keyword(.var), - bindingsBuilder: { - PatternBindingListSyntax { - PatternBindingSyntax( - pattern: IdentifierPatternSyntax(identifier: .identifier(property.name)), - typeAnnotation: TypeAnnotationSyntax( - type: IdentifierTypeSyntax(name: .identifier(property.type.swiftType)) - ), - accessorBlock: AccessorBlockSyntax( - accessors: .accessors( - AccessorDeclListSyntax(accessorDecls) - ) - ) - ) - } - } - ) - ) - ] - if !property.isReadonly { - decls.append(try renderSetterDecl(property: property)) - } - return decls + if let constructor = type.constructor { + decls.append(contentsOf: try renderConstructorDecl(constructor: constructor)) } - let classDecl = try StructDeclSyntax( - leadingTrivia: Self.renderDocumentation(documentation: type.documentation), - name: .identifier(name), - memberBlockBuilder: { - DeclSyntax( - """ - let this: JSObject - """ - ).with(\.trailingTrivia, .newlines(2)) - - DeclSyntax( - """ - init(this: JSObject) { - self.this = this - } - """ - ).with(\.trailingTrivia, .newlines(2)) - DeclSyntax( - """ - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) - } - """ - ).with(\.trailingTrivia, .newlines(2)) + for method in type.staticMethods { + decls.append(contentsOf: try renderStaticMethod(method: method)) + } - if let constructor = type.constructor { - try renderConstructorDecl(constructor: constructor).map { $0.with(\.trailingTrivia, .newlines(2)) } - } + for getter in type.getters { + decls.append(try renderGetterDecl(getter: getter)) + } - for property in type.properties { - try renderPropertyDecl(property: property).map { $0.with(\.trailingTrivia, .newlines(2)) } - } + for setter in type.setters { + decls.append(try renderSetterDecl(setter: setter)) + } - for method in type.methods { - try renderMethod(method: method).map { $0.with(\.trailingTrivia, .newlines(2)) } - } - } - ) + for method in type.methods { + decls.append(contentsOf: try renderMethod(method: method)) + } - return [DeclSyntax(classDecl)] + return decls } static func renderDocumentation(documentation: String?) -> Trivia { @@ -475,18 +460,6 @@ public struct ImportTS { return Trivia(pieces: lines.flatMap { [TriviaPiece.docLineComment("/// \($0)"), .newlines(1)] }) } - static func buildFunctionEffect(throws: Bool, async: Bool) -> FunctionEffectSpecifiersSyntax { - return FunctionEffectSpecifiersSyntax( - asyncSpecifier: `async` ? .keyword(.async) : nil, - throwsClause: `throws` - ? ThrowsClauseSyntax( - throwsSpecifier: .keyword(.throws), - leftParen: .leftParenToken(), - type: IdentifierTypeSyntax(name: .identifier("JSException")), - rightParen: .rightParenToken() - ) : nil - ) - } static func buildAccessorEffect(throws: Bool, async: Bool) -> AccessorEffectSpecifiersSyntax { return AccessorEffectSpecifiersSyntax( asyncSpecifier: `async` ? .keyword(.async) : nil, @@ -501,9 +474,370 @@ public struct ImportTS { } } +/// Unified utility for building Swift function signatures using SwiftSyntax +/// +/// This struct eliminates code duplication by providing a single source of truth +/// for generating Swift function signatures across ImportTS, ExportSwift, and +/// other code generators. +struct SwiftSignatureBuilder { + /// Builds a complete function signature from parameters, return type, and effects + /// + /// - Parameters: + /// - parameters: Array of Parameter structs for Swift function signatures + /// - returnType: The return type of the function + /// - effects: Optional effects (async/throws) + /// - Returns: A FunctionSignatureSyntax node + static func buildFunctionSignature( + parameters: [Parameter], + returnType: BridgeType, + effects: Effects? = nil, + useWildcardLabels: Bool = false + ) -> String { + let parameterClause = buildParameterClause(parameters: parameters, useWildcardLabels: useWildcardLabels) + let effectSpecifiers = effects.flatMap { buildEffectSpecifiers(effects: $0) } + let returnClause = buildReturnClause(returnType: returnType) + var out = "" + out += parameterClause + if let effectSpecifiers { + out += " \(effectSpecifiers)" + } + out += returnClause + return out + } + + /// Builds a function signature for ABI/extern functions using WasmCoreType parameters + /// + /// - Parameters: + /// - abiParameters: Array of (name, WasmCoreType) tuples for ABI signatures + /// - returnType: The return type as WasmCoreType (nil for Void) + /// - effects: Optional effects (async/throws) + /// - Returns: A FunctionSignatureSyntax node + static func buildABIFunctionSignature( + abiParameters: [(name: String, type: WasmCoreType)], + returnType: WasmCoreType?, + effects: Effects? = nil + ) -> String { + var out = "" + out += buildABIParameterClause(abiParameters: abiParameters) + if let effects = effects, let effectSpecifiers = buildEffectSpecifiers(effects: effects) { + out += " \(effectSpecifiers)" + } + out += buildABIReturnClause(returnType: returnType) + return out + } + + /// Builds a parameter clause from an array of Parameter structs + /// + /// - Parameters: + /// - parameters: Array of Parameter structs + /// - useWildcardLabels: If true, all parameters use wildcard labels ("_ name: Type"). + /// If false, handles parameter labels: + /// - If label == name: single identifier (e.g., "count: Int") + /// - If label != name: labeled parameter (e.g., "label count: Int") + /// - If label == nil: wildcard label (e.g., "_ count: Int") + static func buildParameterClause( + parameters: [Parameter], + useWildcardLabels: Bool = false + ) -> String { + var out = "(" + out += parameters.map { param in + let label = param.label ?? param.name + let paramType = buildParameterTypeSyntax(from: param.type) + + if useWildcardLabels { + // Always use wildcard labels: "_ name: Type" + return "_ \(param.name): \(paramType)" + } else if label == param.name { + // External label same as parameter name: "count: Int" + return "\(param.name): \(paramType)" + } else if param.label == nil { + // No label specified: use wildcard "_ name: Type" + return "_ \(param.name): \(paramType)" + } else { + // External label differs: "label count: Int" + return "\(label) \(param.name): \(paramType)" + } + }.joined(separator: ", ") + out += ")" + return out + } + + /// Builds a parameter clause for ABI/extern functions + /// + /// All parameters use wildcard labels: "_ name: Type" + static func buildABIParameterClause( + abiParameters: [(name: String, type: WasmCoreType)] + ) -> String { + "(" + + abiParameters.map { param in + "_ \(param.name): \(param.type.swiftType)" + }.joined(separator: ", ") + ")" + } + + /// Builds a return clause from a BridgeType + /// + /// Always returns a ReturnClauseSyntax, including for Void types + /// (to match original behavior that explicitly includes "-> Void") + static func buildReturnClause(returnType: BridgeType) -> String { + return " -> \(returnType.swiftType)" + } + + /// Builds a return clause for ABI/extern functions + /// + /// Returns nil for Void (when returnType is nil), otherwise returns a ReturnClauseSyntax + static func buildABIReturnClause(returnType: WasmCoreType?) -> String { + guard let returnType = returnType else { + return " -> Void" + } + return " -> \(returnType.swiftType)" + } + + /// Builds effect specifiers (async/throws) from an Effects struct + /// + /// Uses JSException as the thrown error type for throws clauses + static func buildEffectSpecifiers(effects: Effects) -> String? { + guard effects.isAsync || effects.isThrows else { + return nil + } + var items: [String] = [] + if effects.isAsync { items.append("async") } + if effects.isThrows { items.append("throws(JSException)") } + return items.joined(separator: " ") + } + + /// Builds a TypeSyntax node from a BridgeType + /// + /// Converts BridgeType to its Swift type representation as a TypeSyntax node + static func buildTypeSyntax(from type: BridgeType) -> String { + return type.swiftType + } + + /// Builds a parameter type syntax from a BridgeType. + static func buildParameterTypeSyntax(from type: BridgeType) -> String { + switch type { + case .closure(_, useJSTypedClosure: false): + return "@escaping \(type.swiftType)" + default: + return buildTypeSyntax(from: type) + } + } +} + +enum SwiftCodePattern { + /// Builds a conditional compilation block with #if arch(wasm32) and #else fatalError + static func buildWasmConditionalCompilation( + printer: CodeFragmentPrinter, + wasmBody: (_ printer: CodeFragmentPrinter) -> Void + ) { + printer.write("#if arch(wasm32)") + wasmBody(printer) + printer.write("#else") + printer.write("fatalError(\"Only available on WebAssembly\")") + printer.write("#endif") + } + + /// Builds a conditional compilation block with #if arch(wasm32) and #else for declarations + static func buildWasmConditionalCompilationDecls( + printer: CodeFragmentPrinter, + wasmDecl: (_ printer: CodeFragmentPrinter) -> Void, + elseDecl: (_ printer: CodeFragmentPrinter) -> Void + ) { + printer.write("#if arch(wasm32)") + wasmDecl(printer) + printer.write("#else") + elseDecl(printer) + printer.write("#endif") + } + + /// Builds the @_extern attribute for WebAssembly extern function declarations + /// Builds an @_extern function declaration (no body, just the declaration) + static func buildExternFunctionDecl( + printer: CodeFragmentPrinter, + moduleName: String, + abiName: String, + functionName: String, + signature: String + ) { + printer.write(buildExternAttribute(moduleName: moduleName, abiName: abiName)) + printer.write("fileprivate func \(functionName)\(signature)") + } + + /// Builds the standard @_expose and @_cdecl attributes for WebAssembly-exposed functions + static func buildExposeAttributes(abiName: String) -> String { + return """ + @_expose(wasm, "\(abiName)") + @_cdecl("\(abiName)") + """ + } + + /// Builds a function declaration with @_expose/@_cdecl attributes and conditional compilation + static func buildExposedFunctionDecl( + abiName: String, + signature: String, + body: (CodeFragmentPrinter) -> Void + ) -> DeclSyntax { + let printer = CodeFragmentPrinter() + printer.write(buildExposeAttributes(abiName: abiName)) + printer.write("public func _\(abiName)\(signature) {") + printer.indent { + buildWasmConditionalCompilation(printer: printer, wasmBody: body) + } + printer.write("}") + return "\(raw: printer.lines.joined(separator: "\n"))" + } + + /// Builds the @_extern attribute for WebAssembly extern function declarations + static func buildExternAttribute(moduleName: String, abiName: String) -> String { + return "@_extern(wasm, module: \"\(moduleName)\", name: \"\(abiName)\")" + } +} + +extension BridgeType { + struct LoweringParameterInfo { + let loweredParameters: [(name: String, type: WasmCoreType)] + + static let bool = LoweringParameterInfo(loweredParameters: [("value", .i32)]) + static let int = LoweringParameterInfo(loweredParameters: [("value", .i32)]) + static let float = LoweringParameterInfo(loweredParameters: [("value", .f32)]) + static let double = LoweringParameterInfo(loweredParameters: [("value", .f64)]) + static let string = LoweringParameterInfo(loweredParameters: [("value", .i32)]) + static let jsObject = LoweringParameterInfo(loweredParameters: [("value", .i32)]) + static let jsValue = LoweringParameterInfo(loweredParameters: [ + ("kind", .i32), + ("payload1", .i32), + ("payload2", .f64), + ]) + static let void = LoweringParameterInfo(loweredParameters: []) + } + + func loweringParameterInfo(context: BridgeContext = .importTS) throws -> LoweringParameterInfo { + switch self { + case .bool: return .bool + case .int, .uint: return .int + case .float: return .float + case .double: return .double + case .string: return .string + case .jsObject: return .jsObject + case .jsValue: return .jsValue + case .void: return .void + case .closure: + // Swift closure is passed to JS as a JS function reference. + return LoweringParameterInfo(loweredParameters: [("funcRef", .i32)]) + case .unsafePointer: + return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)]) + case .swiftHeapObject: + return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)]) + case .swiftProtocol: + throw BridgeJSCoreError("swiftProtocol is not supported in imported signatures") + case .caseEnum: + switch context { + case .importTS: + throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") + case .exportSwift: + return LoweringParameterInfo(loweredParameters: [("value", .i32)]) + } + case .rawValueEnum(_, let rawType): + let wasmType = rawType.wasmCoreType ?? .i32 + return LoweringParameterInfo(loweredParameters: [("value", wasmType)]) + case .associatedValueEnum: + switch context { + case .importTS: + throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") + case .exportSwift: + return LoweringParameterInfo(loweredParameters: [("caseId", .i32)]) + } + case .swiftStruct: + switch context { + case .importTS: + // Swift structs are bridged as JS objects (object IDs) in imported signatures. + return LoweringParameterInfo(loweredParameters: [("objectId", .i32)]) + case .exportSwift: + return LoweringParameterInfo(loweredParameters: []) + } + case .namespaceEnum: + throw BridgeJSCoreError("Namespace enums cannot be used as parameters") + case .nullable(let wrappedType, _): + let wrappedInfo = try wrappedType.loweringParameterInfo(context: context) + var params = [("isSome", WasmCoreType.i32)] + params.append(contentsOf: wrappedInfo.loweredParameters) + return LoweringParameterInfo(loweredParameters: params) + case .array, .dictionary: + return LoweringParameterInfo(loweredParameters: []) + } + } + + struct LiftingReturnInfo { + let valueToLift: WasmCoreType? + + static let bool = LiftingReturnInfo(valueToLift: .i32) + static let int = LiftingReturnInfo(valueToLift: .i32) + static let float = LiftingReturnInfo(valueToLift: .f32) + static let double = LiftingReturnInfo(valueToLift: .f64) + static let string = LiftingReturnInfo(valueToLift: .i32) + static let jsObject = LiftingReturnInfo(valueToLift: .i32) + static let jsValue = LiftingReturnInfo(valueToLift: nil) + static let void = LiftingReturnInfo(valueToLift: nil) + } + + func liftingReturnInfo( + context: BridgeContext = .importTS + ) throws -> LiftingReturnInfo { + switch self { + case .bool: return .bool + case .int, .uint: return .int + case .float: return .float + case .double: return .double + case .string: return .string + case .jsObject: return .jsObject + case .jsValue: return .jsValue + case .void: return .void + case .closure: + // JS returns a callback ID for closures, which Swift lifts to a typed closure. + return LiftingReturnInfo(valueToLift: .i32) + case .unsafePointer: + return LiftingReturnInfo(valueToLift: .pointer) + case .swiftHeapObject: + return LiftingReturnInfo(valueToLift: .pointer) + case .swiftProtocol: + throw BridgeJSCoreError("swiftProtocol is not supported in imported signatures") + case .caseEnum: + switch context { + case .importTS: + throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") + case .exportSwift: + return LiftingReturnInfo(valueToLift: .i32) + } + case .rawValueEnum(_, let rawType): + let wasmType = rawType.wasmCoreType ?? .i32 + return LiftingReturnInfo(valueToLift: wasmType) + case .associatedValueEnum: + switch context { + case .importTS: + throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") + case .exportSwift: + return LiftingReturnInfo(valueToLift: .i32) + } + case .swiftStruct: + switch context { + case .importTS: + // Swift structs are bridged as JS objects (object IDs) in imported signatures. + return LiftingReturnInfo(valueToLift: .i32) + case .exportSwift: + return LiftingReturnInfo(valueToLift: nil) + } + case .namespaceEnum: + throw BridgeJSCoreError("Namespace enums cannot be used as return values") + case .nullable(let wrappedType, _): + let wrappedInfo = try wrappedType.liftingReturnInfo(context: context) + return LiftingReturnInfo(valueToLift: wrappedInfo.valueToLift) + case .array, .dictionary: + return LiftingReturnInfo(valueToLift: nil) + } + } +} + extension String { - func capitalizedFirstLetter() -> String { - guard !isEmpty else { return self } - return prefix(1).uppercased() + dropFirst() + func backtickIfNeeded() -> String { + return self.isValidSwiftIdentifier(for: .variableName) ? self : "`\(self)`" } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift new file mode 100644 index 000000000..06fb422a9 --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift @@ -0,0 +1,404 @@ +// MARK: - ProgressReporting + +public struct ProgressReporting { + let print: (String) -> Void + + public init(verbose: Bool) { + self.init(print: verbose ? { Swift.print($0) } : { _ in }) + } + + private init(print: @escaping (String) -> Void) { + self.print = print + } + + public static var silent: ProgressReporting { + return ProgressReporting(print: { _ in }) + } + + public func print(_ message: String) { + self.print(message) + } +} + +// MARK: - Profiling + +/// A simple time-profiler API +public final class Profiling { + nonisolated(unsafe) static var current: Profiling? + + let beginEntry: (_ label: String) -> Void + let endEntry: (_ label: String) -> Void + let finalize: () -> Void + + /// Create a profiling instance that outputs Trace Event Format, which + /// can be viewed in chrome://tracing or other compatible viewers. + /// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit?usp=sharing + public static func traceEvent(output: @escaping (String) -> Void) -> Profiling { + let clock = ContinuousClock() + let startTime = clock.now + var firstEntry = true + + func formatTimestamp() -> Int { + let duration = startTime.duration(to: .now) + let (seconds, attoseconds) = duration.components + // Convert to microseconds + return Int(seconds * 1_000_000 + attoseconds / 1_000_000_000_000) + } + + return Profiling( + beginEntry: { label in + let entry = #"{"ph":"B","pid":1,"name":\#(JSON.serialize(label)),"ts":\#(formatTimestamp())}"# + if firstEntry { + firstEntry = false + output("[\n\(entry)") + } else { + output(",\n\(entry)") + } + }, + endEntry: { label in + output(#",\#n{"ph":"E","pid":1,"name":\#(JSON.serialize(label)),"ts":\#(formatTimestamp())}"#) + }, + finalize: { + output("]\n") + } + ) + } + + public init( + beginEntry: @escaping (_ label: String) -> Void, + endEntry: @escaping (_ label: String) -> Void, + finalize: @escaping () -> Void + ) { + self.beginEntry = beginEntry + self.endEntry = endEntry + self.finalize = finalize + } + + public static func with(_ makeCurrent: () -> Profiling?, body: @escaping () throws -> Void) rethrows -> Void { + guard let current = makeCurrent() else { + return try body() + } + defer { current.finalize() } + Profiling.current = current + defer { Profiling.current = nil } + return try body() + } +} + +/// Mark a span of code with a label and measure the duration. +public func withSpan(_ label: String, body: @escaping () throws -> T) rethrows -> T { + guard let profiling = Profiling.current else { + return try body() + } + profiling.beginEntry(label) + defer { + profiling.endEntry(label) + } + return try body() +} + +/// Foundation-less JSON serialization +private enum JSON { + static func serialize(_ value: String) -> String { + // https://www.ietf.org/rfc/rfc4627.txt + var output = "\"" + for scalar in value.unicodeScalars { + switch scalar { + case "\"": + output += "\\\"" + case "\\": + output += "\\\\" + case "\u{08}": + output += "\\b" + case "\u{0C}": + output += "\\f" + case "\n": + output += "\\n" + case "\r": + output += "\\r" + case "\t": + output += "\\t" + case "\u{20}"..."\u{21}", "\u{23}"..."\u{5B}", "\u{5D}"..."\u{10FFFF}": + output.unicodeScalars.append(scalar) + default: + var hex = String(scalar.value, radix: 16, uppercase: true) + hex = String(repeating: "0", count: 4 - hex.count) + hex + output += "\\u" + hex + } + } + output += "\"" + return output + } +} + +// MARK: - DiagnosticError + +import SwiftSyntax +import class Foundation.ProcessInfo + +public struct DiagnosticError: Error { + public let node: Syntax + public let message: String + public let hint: String? + + public init(node: some SyntaxProtocol, message: String, hint: String? = nil) { + self.node = Syntax(node) + self.message = message + self.hint = hint + } + + /// Formats the diagnostic error as a string. + /// + /// - Parameters: + /// - fileName: The name of the file to display in the output. + /// - colorize: Whether to colorize the output with ANSI escape sequences. + /// - Returns: The formatted diagnostic error string. + public func formattedDescription(fileName: String, colorize: Bool = Self.shouldColorize) -> String { + let displayFileName = fileName == "-" ? "" : fileName + let converter = SourceLocationConverter(fileName: displayFileName, tree: node.root) + let startLocation = converter.location(for: node.positionAfterSkippingLeadingTrivia) + let endLocation = converter.location(for: node.endPositionBeforeTrailingTrivia) + + let sourceText = node.root.description + let lines = sourceText.split(omittingEmptySubsequences: false, whereSeparator: \.isNewline) + let startLineIndex = max(0, min(lines.count - 1, startLocation.line - 1)) + let mainLine = String(lines[startLineIndex]) + + let lineNumberWidth = max(3, String(lines.count).count) + + let header: String = { + guard colorize else { + return "\(displayFileName):\(startLocation.line):\(startLocation.column): error: \(message)" + } + return + "\(displayFileName):\(startLocation.line):\(startLocation.column): \(ANSI.boldRed)error: \(ANSI.boldDefault)\(message)\(ANSI.reset)" + }() + + let highlightStartColumn = min(max(1, startLocation.column), mainLine.utf8.count + 1) + let availableColumns = max(0, mainLine.utf8.count - (highlightStartColumn - 1)) + let rawHighlightLength: Int = { + guard availableColumns > 0 else { return 0 } + if startLocation.line == endLocation.line { + return max(1, min(endLocation.column - startLocation.column, availableColumns)) + } else { + return min(1, availableColumns) + } + }() + let highlightLength = min(rawHighlightLength, availableColumns) + + let formattedMainLine: String = { + guard colorize, highlightLength > 0 else { return mainLine } + + let startIndex = Self.index(atUTF8Offset: highlightStartColumn - 1, in: mainLine) + let endIndex = Self.index(atUTF8Offset: highlightStartColumn - 1 + highlightLength, in: mainLine) + + let prefix = String(mainLine[..= 0, lineIndex < lines.count else { continue } + descriptionParts.append( + Self.formatSourceLine( + number: lineIndex + 1, + text: String(lines[lineIndex]), + width: lineNumberWidth, + colorize: colorize + ) + ) + } + + descriptionParts.append( + Self.formatSourceLine( + number: startLocation.line, + text: formattedMainLine, + width: lineNumberWidth, + colorize: colorize + ) + ) + + let pointerSpacing = max(0, highlightStartColumn - 1) + let pointerMessage: String = { + let pointer = String(repeating: " ", count: pointerSpacing) + "`- " + guard colorize else { return pointer + "error: \(message)" } + return pointer + "\(ANSI.boldRed)error: \(ANSI.boldDefault)\(message)\(ANSI.reset)" + }() + descriptionParts.append( + Self.formatSourceLine( + number: nil, + text: pointerMessage, + width: lineNumberWidth, + colorize: colorize + ) + ) + + if startLineIndex + 1 < lines.count { + descriptionParts.append( + Self.formatSourceLine( + number: startLocation.line + 1, + text: String(lines[startLineIndex + 1]), + width: lineNumberWidth, + colorize: colorize + ) + ) + } + + if let hint { + descriptionParts.append("Hint: \(hint)") + } + + return descriptionParts.joined(separator: "\n") + } + + private static func formatSourceLine( + number: Int?, + text: String, + width: Int, + colorize: Bool + ) -> String { + let gutter: String + if let number { + let paddedNumber = String(repeating: " ", count: max(0, width - String(number).count)) + String(number) + gutter = colorize ? ANSI.cyan + paddedNumber + ANSI.reset : paddedNumber + } else { + gutter = String(repeating: " ", count: width) + } + return "\(gutter) | \(text)" + } + + public static var shouldColorize: Bool { + let env = ProcessInfo.processInfo.environment + let termIsDumb = env["TERM"] == "dumb" + return env["NO_COLOR"] == nil && !termIsDumb + } + + private static func index(atUTF8Offset offset: Int, in line: String) -> String.Index { + let clamped = max(0, min(offset, line.utf8.count)) + let utf8Index = line.utf8.index(line.utf8.startIndex, offsetBy: clamped) + // String.Index initializer is guaranteed to succeed because the UTF8 index comes from the same string. + return String.Index(utf8Index, within: line)! + } +} +/// Carries the diagnostics produced during SwiftToSkeleton. +public struct BridgeJSCoreDiagnosticError: Swift.Error, CustomStringConvertible { + public let diagnostics: [(file: String, diagnostic: DiagnosticError)] + + public init(diagnostics: [(file: String, diagnostic: DiagnosticError)]) { + self.diagnostics = diagnostics + } + + public var description: String { + diagnostics + .map { (file, diag) in diag.formattedDescription(fileName: file, colorize: false) } + .joined(separator: "\n") + } +} + +private enum ANSI { + static let reset = "\u{001B}[0;0m" + static let boldRed = "\u{001B}[1;31m" + static let boldDefault = "\u{001B}[1;39m" + static let cyan = "\u{001B}[0;36m" + static let underline = "\u{001B}[4;39m" +} + +// MARK: - BridgeJSCoreError + +public struct BridgeJSCoreError: Swift.Error, CustomStringConvertible { + public let description: String + + public init(_ message: String) { + self.description = message + } +} + +// MARK: - BridgeJSConfig + +import struct Foundation.URL +import struct Foundation.Data +import class Foundation.FileManager +import class Foundation.JSONDecoder + +/// Configuration file representation for BridgeJS. +public struct BridgeJSConfig: Codable { + /// A mapping of tool names to their override paths. + /// + /// If not present, the tool will be searched for in the system PATH. + public var tools: [String: String]? + + /// Whether to expose exported Swift APIs to the global namespace. + /// + /// When `true`, exported functions, classes, and namespaces are available + /// via `globalThis` in JavaScript. When `false`, they are only available + /// through the exports object returned by `createExports()`. + /// + /// Default: `false` + public var exposeToGlobal: Bool + + public init(tools: [String: String]? = nil, exposeToGlobal: Bool = false) { + self.tools = tools + self.exposeToGlobal = exposeToGlobal + } + + enum CodingKeys: String, CodingKey { + case tools + case exposeToGlobal + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + tools = try container.decodeIfPresent([String: String].self, forKey: .tools) + exposeToGlobal = try container.decodeIfPresent(Bool.self, forKey: .exposeToGlobal) ?? false + } + + /// Load the configuration file from the SwiftPM package target directory. + /// + /// Files are loaded **in this order** and merged (later files override earlier ones): + /// 1. `bridge-js.config.json` + /// 2. `bridge-js.config.local.json` + public static func load(targetDirectory: URL) throws -> BridgeJSConfig { + // Define file paths in priority order: base first, then local overrides + let files = [ + targetDirectory.appendingPathComponent("bridge-js.config.json"), + targetDirectory.appendingPathComponent("bridge-js.config.local.json"), + ] + + var config = BridgeJSConfig() + + for file in files { + do { + if let loaded = try loadConfig(from: file) { + config = config.merging(overrides: loaded) + } + } catch { + throw BridgeJSCoreError("Failed to parse \(file.path): \(error)") + } + } + + return config + } + + /// Load a config file from the given URL if it exists, otherwise return nil + private static func loadConfig(from url: URL) throws -> BridgeJSConfig? { + guard FileManager.default.fileExists(atPath: url.path) else { + return nil + } + let data = try Data(contentsOf: url) + return try JSONDecoder().decode(BridgeJSConfig.self, from: data) + } + + /// Merge the current configuration with the overrides. + func merging(overrides: BridgeJSConfig) -> BridgeJSConfig { + return BridgeJSConfig( + tools: (tools ?? [:]).merging(overrides.tools ?? [:], uniquingKeysWith: { $1 }), + exposeToGlobal: overrides.exposeToGlobal + ) + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ProgressReporting.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ProgressReporting.swift deleted file mode 100644 index d1a2aa6d8..000000000 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ProgressReporting.swift +++ /dev/null @@ -1,19 +0,0 @@ -public struct ProgressReporting { - let print: (String) -> Void - - public init(verbose: Bool) { - self.init(print: verbose ? { Swift.print($0) } : { _ in }) - } - - private init(print: @escaping (String) -> Void) { - self.print = print - } - - public static var silent: ProgressReporting { - return ProgressReporting(print: { _ in }) - } - - public func print(_ message: String) { - self.print(message) - } -} diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift new file mode 100644 index 000000000..0cf5a567f --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift @@ -0,0 +1,2566 @@ +import SwiftSyntax +import SwiftSyntaxBuilder +#if canImport(BridgeJSUtilities) +import BridgeJSUtilities +#endif +#if canImport(BridgeJSSkeleton) +import BridgeJSSkeleton +#endif + +/// Builds BridgeJS skeletons from Swift source files using SwiftSyntax walk for API collection. +/// +/// This is a shared entry point for producing: +/// - exported skeletons from `@JS` declarations +/// - imported skeletons from `@JSFunction/@JSGetter/@JSSetter/@JSClass` macro signatures +public final class SwiftToSkeleton { + public let progress: ProgressReporting + public let moduleName: String + public let exposeToGlobal: Bool + + private var sourceFiles: [(sourceFile: SourceFileSyntax, inputFilePath: String)] = [] + let typeDeclResolver: TypeDeclResolver + + public init(progress: ProgressReporting, moduleName: String, exposeToGlobal: Bool) { + self.progress = progress + self.moduleName = moduleName + self.exposeToGlobal = exposeToGlobal + self.typeDeclResolver = TypeDeclResolver() + + // Index known types provided by JavaScriptKit + self.typeDeclResolver.addSourceFile( + """ + @JSClass struct JSPromise {} + """ + ) + } + + public func addSourceFile(_ sourceFile: SourceFileSyntax, inputFilePath: String) { + self.typeDeclResolver.addSourceFile(sourceFile) + sourceFiles.append((sourceFile, inputFilePath)) + } + + public func finalize() throws -> BridgeJSSkeleton { + var perSourceErrors: [(inputFilePath: String, errors: [DiagnosticError])] = [] + var importedFiles: [ImportedFileSkeleton] = [] + var exported = ExportedSkeleton(functions: [], classes: [], enums: [], exposeToGlobal: exposeToGlobal) + + for (sourceFile, inputFilePath) in sourceFiles { + progress.print("Processing \(inputFilePath)") + + let exportCollector = ExportSwiftAPICollector(parent: self) + exportCollector.walk(sourceFile) + + let typeNameCollector = ImportSwiftMacrosJSImportTypeNameCollector(viewMode: .sourceAccurate) + typeNameCollector.walk(sourceFile) + let importCollector = ImportSwiftMacrosAPICollector( + inputFilePath: inputFilePath, + knownJSClassNames: typeNameCollector.typeNames, + parent: self + ) + importCollector.walk(sourceFile) + + let importErrorsFatal = importCollector.errors.filter { !$0.message.contains("Unsupported type '") } + if !exportCollector.errors.isEmpty || !importErrorsFatal.isEmpty { + perSourceErrors.append( + (inputFilePath: inputFilePath, errors: exportCollector.errors + importErrorsFatal) + ) + } + + let importedFile = ImportedFileSkeleton( + functions: importCollector.importedFunctions, + types: importCollector.importedTypes, + globalGetters: importCollector.importedGlobalGetters + ) + if !importedFile.isEmpty { + importedFiles.append(importedFile) + } + exportCollector.finalize(&exported) + } + + if !perSourceErrors.isEmpty { + let diagnostics = perSourceErrors.flatMap { inputFilePath, errors in + errors.map { (file: inputFilePath, diagnostic: $0) } + } + throw BridgeJSCoreDiagnosticError(diagnostics: diagnostics) + } + let importedSkeleton: ImportedModuleSkeleton? = { + let module = ImportedModuleSkeleton(children: importedFiles) + if module.children.allSatisfy({ $0.functions.isEmpty && $0.types.isEmpty && $0.globalGetters.isEmpty }) { + return nil + } + return module + }() + + let exportedSkeleton: ExportedSkeleton? = exported.isEmpty ? nil : exported + return BridgeJSSkeleton(moduleName: moduleName, exported: exportedSkeleton, imported: importedSkeleton) + } + + func lookupType(for type: TypeSyntax, errors: inout [DiagnosticError]) -> BridgeType? { + if let attributedType = type.as(AttributedTypeSyntax.self) { + return lookupType(for: attributedType.baseType, errors: &errors) + } + + if let identifierType = type.as(IdentifierTypeSyntax.self), + identifierType.name.text == "JSTypedClosure", + let genericArgs = identifierType.genericArgumentClause?.arguments, + genericArgs.count == 1, + let argument = genericArgs.firstAsTypeSyntax, + let signatureType = lookupType(for: argument, errors: &errors), + case .closure(let signature, false) = signatureType + { + return .closure(signature, useJSTypedClosure: true) + } + + // (T1, T2, ...) -> R + if let functionType = type.as(FunctionTypeSyntax.self) { + var parameters: [BridgeType] = [] + for param in functionType.parameters { + guard let paramType = lookupType(for: param.type, errors: &errors) else { + return nil + } + parameters.append(paramType) + } + + guard let returnType = lookupType(for: functionType.returnClause.type, errors: &errors) else { + return nil + } + + let isAsync = functionType.effectSpecifiers?.asyncSpecifier != nil + let isThrows = functionType.effectSpecifiers?.throwsClause != nil + + return .closure( + ClosureSignature( + parameters: parameters, + returnType: returnType, + moduleName: moduleName, + isAsync: isAsync, + isThrows: isThrows + ), + useJSTypedClosure: false + ) + } + + // T? + if let optionalType = type.as(OptionalTypeSyntax.self) { + let wrappedType = optionalType.wrappedType + if let baseType = lookupType(for: wrappedType, errors: &errors) { + return .nullable(baseType, .null) + } + } + // JSUndefinedOr + if let identifierType = type.as(IdentifierTypeSyntax.self), + identifierType.name.text == "JSUndefinedOr", + let genericArgs = identifierType.genericArgumentClause?.arguments, + genericArgs.count == 1, + let argType = TypeSyntax(genericArgs.first?.argument) + { + if let baseType = lookupType(for: argType, errors: &errors) { + return .nullable(baseType, .undefined) + } + } + // JavaScriptKit.JSUndefinedOr + if let memberType = type.as(MemberTypeSyntax.self), + let baseType = memberType.baseType.as(IdentifierTypeSyntax.self), + baseType.name.text == "JavaScriptKit", + memberType.name.text == "JSUndefinedOr", + let genericArgs = memberType.genericArgumentClause?.arguments, + genericArgs.count == 1, + let argType = TypeSyntax(genericArgs.first?.argument) + { + if let wrappedType = lookupType(for: argType, errors: &errors) { + return .nullable(wrappedType, .undefined) + } + } + // Optional + if let identifierType = type.as(IdentifierTypeSyntax.self), + identifierType.name.text == "Optional", + let genericArgs = identifierType.genericArgumentClause?.arguments, + genericArgs.count == 1, + let argType = TypeSyntax(genericArgs.first?.argument) + { + if let baseType = lookupType(for: argType, errors: &errors) { + return .nullable(baseType, .null) + } + } + // Swift.Optional + if let memberType = type.as(MemberTypeSyntax.self), + let baseType = memberType.baseType.as(IdentifierTypeSyntax.self), + baseType.name.text == "Swift", + memberType.name.text == "Optional", + let genericArgs = memberType.genericArgumentClause?.arguments, + genericArgs.count == 1, + let argType = TypeSyntax(genericArgs.first?.argument) + { + if let wrappedType = lookupType(for: argType, errors: &errors) { + return .nullable(wrappedType, .null) + } + } + // [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) + } + } + // [String: T] + if let dictType = type.as(DictionaryTypeSyntax.self) { + if let keyType = lookupType(for: dictType.key, errors: &errors), + keyType == .string, + let valueType = lookupType(for: dictType.value, errors: &errors) + { + return .dictionary(valueType) + } + } + // Dictionary + if let identifierType = type.as(IdentifierTypeSyntax.self), + identifierType.name.text == "Dictionary", + let genericArgs = identifierType.genericArgumentClause?.arguments, + genericArgs.count == 2, + let keyArg = TypeSyntax(genericArgs.first?.argument), + let valueArg = TypeSyntax(genericArgs.last?.argument), + let keyType = lookupType(for: keyArg, errors: &errors), + keyType == .string + { + if let valueType = lookupType(for: valueArg, errors: &errors) { + return .dictionary(valueType) + } + } + // Swift.Dictionary + if let memberType = type.as(MemberTypeSyntax.self), + let baseType = memberType.baseType.as(IdentifierTypeSyntax.self), + baseType.name.text == "Swift", + memberType.name.text == "Dictionary", + let genericArgs = memberType.genericArgumentClause?.arguments, + genericArgs.count == 2, + let keyArg = TypeSyntax(genericArgs.first?.argument), + let valueArg = TypeSyntax(genericArgs.last?.argument), + let keyType = lookupType(for: keyArg, errors: &errors), + keyType == .string + { + if let valueType = lookupType(for: valueArg, errors: &errors) { + return .dictionary(valueType) + } + } + 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) + } else { + typeName = type.trimmedDescription + } + if let primitiveType = BridgeType(swiftType: typeName) { + return primitiveType + } + + guard let typeDecl = typeDeclResolver.resolve(type) else { + errors.append( + DiagnosticError( + node: type, + message: "Unsupported type '\(type.trimmedDescription)'.", + hint: "Only primitive types and types defined in the same module are allowed" + ) + ) + return nil + } + + if typeDecl.is(ProtocolDeclSyntax.self) { + let swiftCallName = SwiftToSkeleton.computeSwiftCallName(for: typeDecl, itemName: typeDecl.name.text) + return .swiftProtocol(swiftCallName) + } + + if let enumDecl = typeDecl.as(EnumDeclSyntax.self) { + let swiftCallName = SwiftToSkeleton.computeSwiftCallName(for: enumDecl, itemName: enumDecl.name.text) + let rawTypeString = enumDecl.inheritanceClause?.inheritedTypes.first { inheritedType in + let typeName = inheritedType.type.trimmedDescription + return ExportSwiftConstants.supportedRawTypes.contains(typeName) + }?.type.trimmedDescription + + if let rawType = SwiftEnumRawType(rawTypeString) { + return .rawValueEnum(swiftCallName, rawType) + } else { + let hasAnyCases = enumDecl.memberBlock.members.contains { member in + member.decl.is(EnumCaseDeclSyntax.self) + } + if !hasAnyCases { + return .namespaceEnum(swiftCallName) + } + let hasAssociatedValues = + enumDecl.memberBlock.members.contains { member in + guard let caseDecl = member.decl.as(EnumCaseDeclSyntax.self) else { return false } + return caseDecl.elements.contains { element in + if let params = element.parameterClause?.parameters { + return !params.isEmpty + } + return false + } + } + if hasAssociatedValues { + return .associatedValueEnum(swiftCallName) + } else { + return .caseEnum(swiftCallName) + } + } + } + + if let structDecl = typeDecl.as(StructDeclSyntax.self) { + let swiftCallName = SwiftToSkeleton.computeSwiftCallName(for: structDecl, itemName: structDecl.name.text) + if structDecl.attributes.hasAttribute(name: "JSClass") { + return .jsObject(swiftCallName) + } + return .swiftStruct(swiftCallName) + } + + guard typeDecl.is(ClassDeclSyntax.self) || typeDecl.is(ActorDeclSyntax.self) else { + return nil + } + let swiftCallName = SwiftToSkeleton.computeSwiftCallName(for: typeDecl, itemName: typeDecl.name.text) + + // A type annotated with @JSClass is a JavaScript object wrapper (imported), + // even if it is declared as a Swift class. + if let classDecl = typeDecl.as(ClassDeclSyntax.self), classDecl.attributes.hasAttribute(name: "JSClass") { + return .jsObject(swiftCallName) + } + if let actorDecl = typeDecl.as(ActorDeclSyntax.self), actorDecl.attributes.hasAttribute(name: "JSClass") { + return .jsObject(swiftCallName) + } + + 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 { + var swiftPath: [String] = [] + var currentNode: Syntax? = node.parent + + while let parent = currentNode { + if let enumDecl = parent.as(EnumDeclSyntax.self), + enumDecl.attributes.hasJSAttribute() + { + swiftPath.insert(enumDecl.name.text, at: 0) + } + currentNode = parent.parent + } + + if swiftPath.isEmpty { + return itemName + } else { + return swiftPath.joined(separator: ".") + "." + itemName + } + } + + /// Strips surrounding backticks from an identifier (e.g. "`Foo`" -> "Foo"). + static func normalizeIdentifier(_ name: String) -> String { + guard name.hasPrefix("`"), name.hasSuffix("`"), name.count >= 2 else { + return name + } + return String(name.dropFirst().dropLast()) + } + +} + +private enum ExportSwiftConstants { + static let supportedRawTypes = SwiftEnumRawType.allCases.map { $0.rawValue } +} + +extension AttributeSyntax { + /// The attribute name as text when it is a simple identifier (e.g. "JS", "JSFunction"). + /// Prefer this over `attributeName.trimmedDescription` for name checks to avoid unnecessary string work. + fileprivate var attributeNameText: String? { + attributeName.as(IdentifierTypeSyntax.self)?.name.text + } +} + +extension AttributeListSyntax { + func hasJSAttribute() -> Bool { + firstJSAttribute != nil + } + + var firstJSAttribute: AttributeSyntax? { + first(where: { $0.as(AttributeSyntax.self)?.attributeNameText == "JS" })?.as(AttributeSyntax.self) + } + + /// Returns true if any attribute has the given name (e.g. "JSClass"). + func hasAttribute(name: String) -> Bool { + contains { attribute in + guard let syntax = attribute.as(AttributeSyntax.self) else { return false } + return syntax.attributeNameText == name + } + } +} + +private final class ExportSwiftAPICollector: SyntaxAnyVisitor { + var exportedFunctions: [ExportedFunction] = [] + /// The names of the exported classes, in the order they were written in the source file + var exportedClassNames: [String] = [] + var exportedClassByName: [String: ExportedClass] = [:] + /// The names of the exported enums, in the order they were written in the source file + var exportedEnumNames: [String] = [] + var exportedEnumByName: [String: ExportedEnum] = [:] + /// The names of the exported protocols, in the order they were written in the source file + var exportedProtocolNames: [String] = [] + var exportedProtocolByName: [String: ExportedProtocol] = [:] + /// The names of the exported structs, in the order they were written in the source file + var exportedStructNames: [String] = [] + var exportedStructByName: [String: ExportedStruct] = [:] + var errors: [DiagnosticError] = [] + + func finalize(_ result: inout ExportedSkeleton) { + result.functions.append(contentsOf: exportedFunctions) + result.classes.append(contentsOf: exportedClassNames.map { exportedClassByName[$0]! }) + result.enums.append(contentsOf: exportedEnumNames.map { exportedEnumByName[$0]! }) + result.structs.append(contentsOf: exportedStructNames.map { exportedStructByName[$0]! }) + result.protocols.append(contentsOf: exportedProtocolNames.map { exportedProtocolByName[$0]! }) + } + + /// Creates a unique key by combining name and namespace + private func makeKey(name: String, namespace: [String]?) -> String { + if let namespace = namespace, !namespace.isEmpty { + return "\(namespace.joined(separator: ".")).\(name)" + } else { + return name + } + } + + struct NamespaceResolution { + let namespace: [String]? + let isValid: Bool + } + + /// Resolves and validates namespace from both @JS attribute and computed (nested) namespace + /// Returns the effective namespace and whether validation succeeded + private func resolveNamespace( + from jsAttribute: AttributeSyntax, + for node: some SyntaxProtocol, + declarationType: String + ) -> NamespaceResolution { + let attributeNamespace = extractNamespace(from: jsAttribute) + let computedNamespace = computeNamespace(for: node) + + if computedNamespace != nil && attributeNamespace != nil { + diagnose( + node: jsAttribute, + message: "Nested \(declarationType)s cannot specify their own namespace", + hint: + "Remove the namespace from @JS attribute - nested \(declarationType)s inherit namespace from parent" + ) + return NamespaceResolution(namespace: nil, isValid: false) + } + + return NamespaceResolution(namespace: computedNamespace ?? attributeNamespace, isValid: true) + } + + enum State { + case topLevel + case classBody(name: String, key: String) + case enumBody(name: String, key: String) + case protocolBody(name: String, key: String) + case structBody(name: String, key: String) + } + + struct StateStack { + private var states: [State] + var current: State { + return states.last! + } + + init(_ initialState: State) { + self.states = [initialState] + } + mutating func push(state: State) { + states.append(state) + } + + mutating func pop() { + _ = states.removeLast() + } + } + + var stateStack: StateStack = StateStack(.topLevel) + var state: State { + return stateStack.current + } + let parent: SwiftToSkeleton + + init(parent: SwiftToSkeleton) { + self.parent = parent + super.init(viewMode: .sourceAccurate) + } + + private func diagnose(node: some SyntaxProtocol, message: String, hint: String? = nil) { + errors.append(DiagnosticError(node: node, message: message, hint: hint)) + } + + private func withLookupErrors(_ body: (inout [DiagnosticError]) -> T) -> T { + var errs = self.errors + defer { self.errors = errs } + return body(&errs) + } + + private func diagnoseNestedOptional(node: some SyntaxProtocol, type: String) { + diagnose( + node: node, + message: "Nested optional types are not supported: \(type)", + hint: "Use a single optional like String? instead of String?? or Optional>" + ) + } + + /// Detects whether given expression is supported as default parameter value + private func isSupportedDefaultValueExpression(_ initClause: InitializerClauseSyntax) -> Bool { + let expression = initClause.value + + // Function calls are checked later in extractDefaultValue (as constructors are allowed) + // 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 } + + // Method call chains (e.g., obj.foo()) + if let memberExpression = expression.as(MemberAccessExprSyntax.self), + memberExpression.base?.is(FunctionCallExprSyntax.self) == true + { + return false + } + + return true + } + + /// Extract enum case value from member access expression + private func extractEnumCaseValue( + from memberExpr: MemberAccessExprSyntax, + type: BridgeType + ) -> DefaultValue? { + let caseName = memberExpr.declName.baseName.text + + let enumName: String? + switch type { + case .caseEnum(let name), .rawValueEnum(let name, _), .associatedValueEnum(let name): + enumName = name + case .nullable(let wrappedType, _): + switch wrappedType { + case .caseEnum(let name), .rawValueEnum(let name, _), .associatedValueEnum(let name): + enumName = name + default: + return nil + } + default: + return nil + } + + guard let enumName = enumName else { return nil } + + if memberExpr.base == nil { + return .enumCase(enumName, caseName) + } + + if let baseExpr = memberExpr.base?.as(DeclReferenceExprSyntax.self) { + let baseName = baseExpr.baseName.text + let lastComponent = enumName.split(separator: ".").last.map(String.init) ?? enumName + if baseName == enumName || baseName == lastComponent { + return .enumCase(enumName, caseName) + } + } + + return nil + } + + /// Extracts default value from parameter's default value clause + private func extractDefaultValue( + from defaultClause: InitializerClauseSyntax?, + type: BridgeType + ) -> DefaultValue? { + guard let defaultClause = defaultClause else { + return nil + } + + if !isSupportedDefaultValueExpression(defaultClause) { + diagnose( + node: defaultClause, + message: "Complex default parameter expressions are not supported", + hint: "Use simple literal values (e.g., \"text\", 42, true, nil) or simple constants" + ) + return nil + } + + let expr = defaultClause.value + + if expr.is(NilLiteralExprSyntax.self) { + guard case .nullable = type else { + diagnose( + node: expr, + message: "nil is only valid for optional parameters", + hint: "Make the parameter optional by adding ? to the type" + ) + return nil + } + return .null + } + + if let memberExpr = expr.as(MemberAccessExprSyntax.self), + let enumValue = extractEnumCaseValue(from: memberExpr, type: type) + { + return enumValue + } + + if let funcCall = expr.as(FunctionCallExprSyntax.self) { + 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 + } + + diagnose( + node: expr, + message: "Unsupported default parameter value expression", + hint: "Use simple literal values like \"text\", 42, true, false, nil, or enum cases like .caseName" + ) + return nil + } + + /// Extracts default value from a constructor call expression + private func extractConstructorDefaultValue( + from funcCall: FunctionCallExprSyntax, + type: BridgeType + ) -> DefaultValue? { + guard let calledExpr = funcCall.calledExpression.as(DeclReferenceExprSyntax.self) else { + diagnose( + node: funcCall, + message: "Complex constructor expressions are not supported", + hint: "Use a simple constructor call like ClassName() or ClassName(arg: value)" + ) + return nil + } + + let typeName = calledExpr.baseName.text + + let isStructType: Bool + let expectedTypeName: String? + switch type { + case .swiftStruct(let name), .nullable(.swiftStruct(let name), _): + isStructType = true + expectedTypeName = name.split(separator: ".").last.map(String.init) + case .swiftHeapObject(let name), .nullable(.swiftHeapObject(let name), _): + isStructType = false + expectedTypeName = name.split(separator: ".").last.map(String.init) + default: + diagnose( + node: funcCall, + message: "Constructor calls are only supported for class and struct types", + hint: "Parameter type should be a Swift class or struct" + ) + return nil + } + + guard let expectedTypeName = expectedTypeName, typeName == expectedTypeName else { + diagnose( + node: funcCall, + message: "Constructor type name '\(typeName)' doesn't match parameter type", + hint: "Ensure the constructor matches the parameter type" + ) + return nil + } + + if isStructType { + // For structs, extract field name/value pairs + var fields: [DefaultValueField] = [] + for argument in funcCall.arguments { + guard let fieldName = argument.label?.text else { + diagnose( + node: argument, + message: "Struct initializer arguments must have labels", + hint: "Use labeled arguments like MyStruct(x: 1, y: 2)" + ) + return nil + } + guard let fieldValue = extractLiteralValue(from: argument.expression) else { + diagnose( + node: argument.expression, + message: "Struct field value must be a literal", + hint: "Use simple literals like \"text\", 42, true, false in struct fields" + ) + return nil + } + fields.append(DefaultValueField(name: fieldName, value: fieldValue)) + } + return .structLiteral(typeName, fields) + } else { + if funcCall.arguments.isEmpty { + return .object(typeName) + } + + var constructorArgs: [DefaultValue] = [] + for argument in funcCall.arguments { + guard let argValue = extractLiteralValue(from: argument.expression) else { + diagnose( + node: argument.expression, + message: "Constructor argument must be a literal value", + hint: "Use simple literals like \"text\", 42, true, false in constructor arguments" + ) + return nil + } + constructorArgs.append(argValue) + } + return .objectWithArguments(typeName, constructorArgs) + } + } + + /// Extracts a literal value from an expression with optional type checking + private func extractLiteralValue(from expr: ExprSyntax, type: BridgeType? = nil) -> DefaultValue? { + if expr.is(NilLiteralExprSyntax.self) { + return .null + } + + if let stringLiteral = expr.as(StringLiteralExprSyntax.self), + let segment = stringLiteral.segments.first?.as(StringSegmentSyntax.self) + { + let value = DefaultValue.string(segment.content.text) + if let type = type, !type.isCompatibleWith(.string) { + return nil + } + return value + } + + if let boolLiteral = expr.as(BooleanLiteralExprSyntax.self) { + let value = DefaultValue.bool(boolLiteral.literal.text == "true") + if let type = type, !type.isCompatibleWith(.bool) { + return nil + } + return value + } + + var numericExpr = expr + var isNegative = false + if let prefixExpr = expr.as(PrefixOperatorExprSyntax.self), + prefixExpr.operator.text == "-" + { + numericExpr = prefixExpr.expression + isNegative = true + } + + if let intLiteral = numericExpr.as(IntegerLiteralExprSyntax.self), + let intValue = Int(intLiteral.literal.text) + { + let value = DefaultValue.int(isNegative ? -intValue : intValue) + if let type = type, !type.isCompatibleWith(.int) { + return nil + } + return value + } + + if let floatLiteral = numericExpr.as(FloatLiteralExprSyntax.self) { + if let floatValue = Float(floatLiteral.literal.text) { + let value = DefaultValue.float(isNegative ? -floatValue : floatValue) + if type == nil || type?.isCompatibleWith(.float) == true { + return value + } + } + if let doubleValue = Double(floatLiteral.literal.text) { + let value = DefaultValue.double(isNegative ? -doubleValue : doubleValue) + if type == nil || type?.isCompatibleWith(.double) == true { + return value + } + } + } + + 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 .nullable(.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, + allowDefaults: Bool = true + ) -> [Parameter] { + var parameters: [Parameter] = [] + + for param in parameterClause.parameters { + let resolvedType = withLookupErrors { self.parent.lookupType(for: param.type, errors: &$0) } + guard let type = resolvedType else { + continue // Skip unsupported types + } + if case .closure(let signature, _) = type { + if signature.isAsync { + diagnose( + node: param.type, + message: "Async is not supported for Swift closures yet." + ) + continue + } + if signature.isThrows { + diagnose( + node: param.type, + message: "Throws is not supported for Swift closures yet." + ) + continue + } + } + if case .nullable(let wrappedType, _) = type, wrappedType.isOptional { + diagnoseNestedOptional(node: param.type, type: param.type.trimmedDescription) + continue + } + if case .nullable(let wrappedType, _) = type, wrappedType.isOptional { + diagnoseNestedOptional(node: param.type, type: param.type.trimmedDescription) + continue + } + + let name = param.secondName?.text ?? param.firstName.text + let label = param.firstName.text + + let defaultValue: DefaultValue? + if allowDefaults { + defaultValue = extractDefaultValue(from: param.defaultValue, type: type) + } else { + defaultValue = nil + } + + parameters.append(Parameter(label: label, name: name, type: type, defaultValue: defaultValue)) + } + + return parameters + } + + override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind { + guard node.attributes.hasJSAttribute() else { + return .skipChildren + } + + let isStatic = node.modifiers.contains { modifier in + modifier.name.tokenKind == .keyword(.static) || modifier.name.tokenKind == .keyword(.class) + } + + switch state { + case .topLevel: + if isStatic { + diagnose(node: node, message: "Top-level functions cannot be static") + return .skipChildren + } + if let exportedFunction = visitFunction(node: node, isStatic: false) { + exportedFunctions.append(exportedFunction) + } + return .skipChildren + case .classBody(let className, let classKey): + if let exportedFunction = visitFunction( + node: node, + isStatic: isStatic, + className: className, + classKey: classKey + ) { + exportedClassByName[classKey]?.methods.append(exportedFunction) + } + return .skipChildren + case .enumBody(let enumName, let enumKey): + if !isStatic { + diagnose(node: node, message: "Only static functions are supported in enums") + return .skipChildren + } + if let exportedFunction = visitFunction(node: node, isStatic: isStatic, enumName: enumName) { + if var currentEnum = exportedEnumByName[enumKey] { + currentEnum.staticMethods.append(exportedFunction) + exportedEnumByName[enumKey] = currentEnum + } + } + return .skipChildren + case .protocolBody(_, _): + // Protocol methods are handled in visitProtocolMethod during protocol parsing + return .skipChildren + case .structBody(let structName, let structKey): + if let exportedFunction = visitFunction(node: node, isStatic: isStatic, structName: structName) { + if var currentStruct = exportedStructByName[structKey] { + currentStruct.methods.append(exportedFunction) + exportedStructByName[structKey] = currentStruct + } + } + return .skipChildren + } + } + + private func visitFunction( + node: FunctionDeclSyntax, + isStatic: Bool, + className: String? = nil, + classKey: String? = nil, + enumName: String? = nil, + structName: String? = nil + ) -> ExportedFunction? { + guard let jsAttribute = node.attributes.firstJSAttribute else { + return nil + } + + let name = node.name.text + + let attributeNamespace = extractNamespace(from: jsAttribute) + let computedNamespace = computeNamespace(for: node) + + let finalNamespace: [String]? + + if let computed = computedNamespace, !computed.isEmpty { + finalNamespace = computed + } else { + finalNamespace = attributeNamespace + } + + if attributeNamespace != nil, case .classBody = state { + diagnose( + node: jsAttribute, + message: "Namespace is only needed in top-level declaration", + hint: "Remove the namespace from @JS attribute or move this function to top-level" + ) + } + + if attributeNamespace != nil, case .enumBody = state { + diagnose( + node: jsAttribute, + message: "Namespace is not supported for enum static functions", + hint: "Remove the namespace from @JS attribute - enum functions inherit namespace from enum" + ) + } + + let parameters = parseParameters(from: node.signature.parameterClause, allowDefaults: true) + let returnType: BridgeType + if let returnClause = node.signature.returnClause { + let resolvedType = withLookupErrors { self.parent.lookupType(for: returnClause.type, errors: &$0) } + + if let type = resolvedType, case .nullable(let wrappedType, _) = type, wrappedType.isOptional { + diagnoseNestedOptional(node: returnClause.type, type: returnClause.type.trimmedDescription) + return nil + } + + guard let type = resolvedType else { return nil } + returnType = type + } else { + returnType = .void + } + + let abiName: String + let staticContext: StaticContext? + + switch state { + case .topLevel: + staticContext = nil + case .classBody(let className, _): + if isStatic { + staticContext = .className(className) + } else { + staticContext = nil + } + case .enumBody(let enumName, let enumKey): + if !isStatic { + diagnose(node: node, message: "Only static functions are supported in enums") + return nil + } + + let isNamespaceEnum = exportedEnumByName[enumKey]?.cases.isEmpty ?? true + let swiftCallName = exportedEnumByName[enumKey]?.swiftCallName ?? enumName + staticContext = isNamespaceEnum ? .namespaceEnum(swiftCallName) : .enumName(enumName) + case .protocolBody(_, _): + return nil + case .structBody(let structName, _): + if isStatic { + staticContext = .structName(structName) + } else { + staticContext = nil + } + } + + let classNameForABI: String? + switch state { + case .classBody(let className, _): + classNameForABI = className + case .structBody(let structName, _): + classNameForABI = structName + default: + classNameForABI = nil + } + abiName = ABINameGenerator.generateABIName( + baseName: name, + namespace: finalNamespace, + staticContext: isStatic ? staticContext : nil, + className: classNameForABI + ) + + guard let effects = collectEffects(signature: node.signature, isStatic: isStatic) else { + return nil + } + + return ExportedFunction( + name: name, + abiName: abiName, + parameters: parameters, + returnType: returnType, + effects: effects, + namespace: finalNamespace, + staticContext: staticContext + ) + } + + private func collectEffects(signature: FunctionSignatureSyntax, isStatic: Bool = false) -> Effects? { + let isAsync = signature.effectSpecifiers?.asyncSpecifier != nil + var isThrows = false + if let throwsClause: ThrowsClauseSyntax = signature.effectSpecifiers?.throwsClause { + // Limit the thrown type to JSException for now + guard let thrownType = throwsClause.type else { + diagnose( + node: throwsClause, + message: "Thrown type is not specified, only JSException is supported for now" + ) + return nil + } + guard thrownType.trimmedDescription == "JSException" else { + diagnose( + node: throwsClause, + message: "Only JSException is supported for thrown type, got \(thrownType.trimmedDescription)" + ) + return nil + } + isThrows = true + } + return Effects(isAsync: isAsync, isThrows: isThrows, isStatic: isStatic) + } + + private func extractNamespace( + from jsAttribute: AttributeSyntax + ) -> [String]? { + guard let arguments = jsAttribute.arguments?.as(LabeledExprListSyntax.self) else { + return nil + } + + guard let namespaceArg = arguments.first(where: { $0.label?.text == "namespace" }), + let stringLiteral = namespaceArg.expression.as(StringLiteralExprSyntax.self), + let namespaceString = stringLiteral.segments.first?.as(StringSegmentSyntax.self)?.content.text + else { + return nil + } + + return namespaceString.split(separator: ".").map(String.init) + } + + private func extractEnumStyle( + from jsAttribute: AttributeSyntax + ) -> EnumEmitStyle? { + guard let arguments = jsAttribute.arguments?.as(LabeledExprListSyntax.self), + let styleArg = arguments.first(where: { $0.label?.text == "enumStyle" }) + else { + return nil + } + let text = styleArg.expression.trimmedDescription + if text.contains("tsEnum") { + return .tsEnum + } + if text.contains("const") { + return .const + } + return nil + } + + override func visit(_ node: InitializerDeclSyntax) -> SyntaxVisitorContinueKind { + guard let jsAttribute = node.attributes.firstJSAttribute else { return .skipChildren } + + switch state { + case .classBody(let className, let classKey): + if extractNamespace(from: jsAttribute) != nil { + diagnose( + node: jsAttribute, + message: "Namespace is not supported for initializer declarations", + hint: "Remove the namespace from @JS attribute" + ) + } + + let parameters = parseParameters(from: node.signature.parameterClause, allowDefaults: true) + + guard let effects = collectEffects(signature: node.signature) else { + return .skipChildren + } + + let constructor = ExportedConstructor( + abiName: "bjs_\(className)_init", + parameters: parameters, + effects: effects + ) + exportedClassByName[classKey]?.constructor = constructor + + case .structBody(let structName, let structKey): + if extractNamespace(from: jsAttribute) != nil { + diagnose( + node: jsAttribute, + message: "Namespace is not supported for initializer declarations", + hint: "Remove the namespace from @JS attribute" + ) + } + + let parameters = parseParameters(from: node.signature.parameterClause, allowDefaults: true) + + guard let effects = collectEffects(signature: node.signature) else { + return .skipChildren + } + + let constructor = ExportedConstructor( + abiName: "bjs_\(structName)_init", + parameters: parameters, + effects: effects + ) + exportedStructByName[structKey]?.constructor = constructor + + case .enumBody(_, _): + diagnose(node: node, message: "Initializers are not supported inside enums") + + case .topLevel, .protocolBody(_, _): + diagnose(node: node, message: "@JS init must be inside a @JS class or struct") + } + + return .skipChildren + } + + override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind { + guard let jsAttribute = node.attributes.firstJSAttribute else { return .skipChildren } + + let isStatic = node.modifiers.contains { modifier in + modifier.name.tokenKind == .keyword(.static) || modifier.name.tokenKind == .keyword(.class) + } + + let attributeNamespace = extractNamespace(from: jsAttribute) + if attributeNamespace != nil { + diagnose( + node: jsAttribute, + message: "Namespace parameter within @JS attribute is not supported for property declarations", + hint: + "Remove the namespace from @JS attribute. If you need dedicated namespace, consider using a nested enum or class instead." + ) + } + + let computedNamespace = computeNamespace(for: node) + let finalNamespace: [String]? + + if let computed = computedNamespace, !computed.isEmpty { + finalNamespace = computed + } else { + finalNamespace = nil + } + + // Determine static context and validate placement + let staticContext: StaticContext? + + switch state { + case .classBody(let className, _): + staticContext = isStatic ? .className(className) : nil + case .enumBody(let enumName, let enumKey): + if !isStatic { + diagnose(node: node, message: "Only static properties are supported in enums") + return .skipChildren + } + let isNamespaceEnum = exportedEnumByName[enumKey]?.cases.isEmpty ?? true + // Use swiftCallName for the full Swift call path (handles nested enums correctly) + let swiftCallName = exportedEnumByName[enumKey]?.swiftCallName ?? enumName + staticContext = + isStatic ? (isNamespaceEnum ? .namespaceEnum(swiftCallName) : .enumName(swiftCallName)) : nil + case .topLevel: + diagnose(node: node, message: "@JS var must be inside a @JS class or enum") + return .skipChildren + case .protocolBody(let protocolName, let protocolKey): + return visitProtocolProperty(node: node, protocolName: protocolName, protocolKey: protocolKey) + case .structBody(let structName, _): + if isStatic { + staticContext = .structName(structName) + } else { + diagnose(node: node, message: "@JS var must be static in structs (instance fields don't need @JS)") + return .skipChildren + } + } + + // Process each binding (variable declaration) + for binding in node.bindings { + guard let pattern = binding.pattern.as(IdentifierPatternSyntax.self) else { + diagnose(node: binding.pattern, message: "Complex patterns not supported for @JS properties") + continue + } + + let propertyName = pattern.identifier.text + + guard let typeAnnotation = binding.typeAnnotation else { + diagnose(node: binding, message: "@JS property must have explicit type annotation") + continue + } + + guard let propertyType = withLookupErrors({ self.parent.lookupType(for: typeAnnotation.type, errors: &$0) }) + else { + continue + } + + // Check if property is readonly + let isLet = node.bindingSpecifier.tokenKind == .keyword(.let) + let isGetterOnly = node.bindings.contains(where: { self.hasOnlyGetter($0.accessorBlock) }) + + let isReadonly = isLet || isGetterOnly + + let exportedProperty = ExportedProperty( + name: propertyName, + type: propertyType, + isReadonly: isReadonly, + isStatic: isStatic, + namespace: finalNamespace, + staticContext: staticContext + ) + + if case .enumBody(_, let key) = state { + if var currentEnum = exportedEnumByName[key] { + currentEnum.staticProperties.append(exportedProperty) + exportedEnumByName[key] = currentEnum + } + } else if case .structBody(_, let key) = state { + exportedStructByName[key]?.properties.append(exportedProperty) + } else if case .classBody(_, let key) = state { + exportedClassByName[key]?.properties.append(exportedProperty) + } + } + + return .skipChildren + } + + override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { + let name = node.name.text + + guard let jsAttribute = node.attributes.firstJSAttribute else { + return .skipChildren + } + + let namespaceResult = resolveNamespace(from: jsAttribute, for: node, declarationType: "class") + guard namespaceResult.isValid else { + return .skipChildren + } + let swiftCallName = SwiftToSkeleton.computeSwiftCallName(for: node, itemName: name) + let explicitAccessControl = computeExplicitAtLeastInternalAccessControl( + for: node, + message: "Class visibility must be at least internal" + ) + let exportedClass = ExportedClass( + name: name, + swiftCallName: swiftCallName, + explicitAccessControl: explicitAccessControl, + constructor: nil, + methods: [], + properties: [], + namespace: namespaceResult.namespace + ) + let uniqueKey = makeKey(name: name, namespace: namespaceResult.namespace) + + stateStack.push(state: .classBody(name: name, key: uniqueKey)) + exportedClassByName[uniqueKey] = exportedClass + exportedClassNames.append(uniqueKey) + return .visitChildren + } + + override func visitPost(_ node: ClassDeclSyntax) { + // Make sure we pop the state stack only if we're in a class body state (meaning we successfully pushed) + if case .classBody(_, _) = stateStack.current { + stateStack.pop() + } + } + + override func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind { + guard let jsAttribute = node.attributes.firstJSAttribute else { + return .skipChildren + } + + let name = node.name.text + + let rawType: String? = node.inheritanceClause?.inheritedTypes.first { inheritedType in + let typeName = inheritedType.type.trimmedDescription + return ExportSwiftConstants.supportedRawTypes.contains(typeName) + }?.type.trimmedDescription + + let namespaceResult = resolveNamespace(from: jsAttribute, for: node, declarationType: "enum") + guard namespaceResult.isValid else { + return .skipChildren + } + let emitStyle = extractEnumStyle(from: jsAttribute) ?? .const + let swiftCallName = SwiftToSkeleton.computeSwiftCallName(for: node, itemName: name) + let explicitAccessControl = computeExplicitAtLeastInternalAccessControl( + for: node, + message: "Enum visibility must be at least internal" + ) + + let tsFullPath: String + if let namespace = namespaceResult.namespace, !namespace.isEmpty { + tsFullPath = namespace.joined(separator: ".") + "." + name + } else { + tsFullPath = name + } + + // Create enum directly in dictionary + let exportedEnum = ExportedEnum( + name: name, + swiftCallName: swiftCallName, + tsFullPath: tsFullPath, + explicitAccessControl: explicitAccessControl, + cases: [], // Will be populated in visit(EnumCaseDeclSyntax) + rawType: SwiftEnumRawType(rawType), + namespace: namespaceResult.namespace, + emitStyle: emitStyle, + staticMethods: [], + staticProperties: [] + ) + + let enumUniqueKey = makeKey(name: name, namespace: namespaceResult.namespace) + exportedEnumByName[enumUniqueKey] = exportedEnum + exportedEnumNames.append(enumUniqueKey) + + stateStack.push(state: .enumBody(name: name, key: enumUniqueKey)) + + return .visitChildren + } + + override func visitPost(_ node: EnumDeclSyntax) { + guard let jsAttribute = node.attributes.firstJSAttribute else { + // Only pop if we have a valid enum that was processed + if case .enumBody(_, _) = stateStack.current { + stateStack.pop() + } + return + } + + guard case .enumBody(_, let enumKey) = stateStack.current else { + return + } + + guard let exportedEnum = exportedEnumByName[enumKey] else { + stateStack.pop() + return + } + + let emitStyle = exportedEnum.emitStyle + + if case .tsEnum = emitStyle { + if exportedEnum.rawType == .bool { + diagnose( + node: jsAttribute, + message: "TypeScript enum style is not supported for Bool raw-value enums", + hint: "Use enumStyle: .const or change the raw type to String or a numeric type" + ) + } + if !exportedEnum.staticMethods.isEmpty { + diagnose( + node: jsAttribute, + message: "TypeScript enum style does not support static functions", + hint: "Use enumStyle: .const to generate a const object that supports static functions" + ) + } + } + + if exportedEnum.cases.contains(where: { !$0.associatedValues.isEmpty }) { + if case .tsEnum = emitStyle { + diagnose( + node: jsAttribute, + message: "TypeScript enum style is not supported for associated value enums", + hint: "Use enumStyle: .const in order to map associated-value enums" + ) + } + for enumCase in exportedEnum.cases { + for associatedValue in enumCase.associatedValues { + switch associatedValue.type { + case .string, .int, .float, .double, .bool, .caseEnum, .rawValueEnum, + .swiftStruct, .swiftHeapObject, .jsObject, .associatedValueEnum, .array: + break + case .nullable(let wrappedType, _): + switch wrappedType { + case .string, .int, .float, .double, .bool, .caseEnum, .rawValueEnum, + .swiftStruct, .swiftHeapObject, .jsObject, .associatedValueEnum, .array: + break + default: + diagnose( + node: node, + message: "Unsupported associated value type: \(associatedValue.type.swiftType)", + hint: + "Only primitive types, enums, structs, classes, JSObject, arrays, and their optionals are supported in associated-value enums" + ) + } + default: + diagnose( + node: node, + message: "Unsupported associated value type: \(associatedValue.type.swiftType)", + hint: + "Only primitive types, enums, structs, classes, JSObject, arrays, and their optionals are supported in associated-value enums" + ) + } + } + } + } + + stateStack.pop() + } + + override func visit(_ node: ProtocolDeclSyntax) -> SyntaxVisitorContinueKind { + guard let jsAttribute = node.attributes.firstJSAttribute else { + return .skipChildren + } + + let name = node.name.text + + let namespaceResult = resolveNamespace(from: jsAttribute, for: node, declarationType: "protocol") + guard namespaceResult.isValid else { + return .skipChildren + } + _ = computeExplicitAtLeastInternalAccessControl( + for: node, + message: "Protocol visibility must be at least internal" + ) + + let protocolUniqueKey = makeKey(name: name, namespace: namespaceResult.namespace) + + exportedProtocolByName[protocolUniqueKey] = ExportedProtocol( + name: name, + methods: [], + properties: [], + namespace: namespaceResult.namespace + ) + + stateStack.push(state: .protocolBody(name: name, key: protocolUniqueKey)) + + var methods: [ExportedFunction] = [] + for member in node.memberBlock.members { + if let funcDecl = member.decl.as(FunctionDeclSyntax.self) { + if let exportedFunction = visitProtocolMethod( + node: funcDecl, + protocolName: name, + namespace: namespaceResult.namespace + ) { + methods.append(exportedFunction) + } + } else if let varDecl = member.decl.as(VariableDeclSyntax.self) { + _ = visitProtocolProperty(node: varDecl, protocolName: name, protocolKey: protocolUniqueKey) + } + } + + let exportedProtocol = ExportedProtocol( + name: name, + methods: methods, + properties: exportedProtocolByName[protocolUniqueKey]?.properties ?? [], + namespace: namespaceResult.namespace + ) + + exportedProtocolByName[protocolUniqueKey] = exportedProtocol + exportedProtocolNames.append(protocolUniqueKey) + + stateStack.pop() + + return .skipChildren + } + + override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { + guard let jsAttribute = node.attributes.firstJSAttribute else { + return .skipChildren + } + + let name = node.name.text + + let namespaceResult = resolveNamespace(from: jsAttribute, for: node, declarationType: "struct") + guard namespaceResult.isValid else { + return .skipChildren + } + let swiftCallName = SwiftToSkeleton.computeSwiftCallName(for: node, itemName: name) + let explicitAccessControl = computeExplicitAtLeastInternalAccessControl( + for: node, + message: "Struct visibility must be at least internal" + ) + + var properties: [ExportedProperty] = [] + + // Process all variables in struct as readonly (value semantics) and don't require @JS + for member in node.memberBlock.members { + if let varDecl = member.decl.as(VariableDeclSyntax.self) { + let isStatic = varDecl.modifiers.contains { modifier in + modifier.name.tokenKind == .keyword(.static) || modifier.name.tokenKind == .keyword(.class) + } + + // Handled with error in visitVariable + if varDecl.attributes.hasJSAttribute() { + continue + } + // Skips static non-@JS properties + if isStatic { + continue + } + + for binding in varDecl.bindings { + guard let pattern = binding.pattern.as(IdentifierPatternSyntax.self) else { + continue + } + + let fieldName = pattern.identifier.text + + guard let typeAnnotation = binding.typeAnnotation else { + diagnose(node: binding, message: "Struct field must have explicit type annotation") + continue + } + + guard + let fieldType = withLookupErrors({ + self.parent.lookupType(for: typeAnnotation.type, errors: &$0) + }) + else { + continue + } + + let property = ExportedProperty( + name: fieldName, + type: fieldType, + isReadonly: true, + isStatic: false, + namespace: namespaceResult.namespace, + staticContext: nil + ) + properties.append(property) + } + } + } + + let structUniqueKey = makeKey(name: name, namespace: namespaceResult.namespace) + let exportedStruct = ExportedStruct( + name: name, + swiftCallName: swiftCallName, + explicitAccessControl: explicitAccessControl, + properties: properties, + methods: [], + namespace: namespaceResult.namespace + ) + + exportedStructByName[structUniqueKey] = exportedStruct + exportedStructNames.append(structUniqueKey) + + stateStack.push(state: .structBody(name: name, key: structUniqueKey)) + + return .visitChildren + } + + override func visitPost(_ node: StructDeclSyntax) { + if case .structBody(_, _) = stateStack.current { + stateStack.pop() + } + } + + private func visitProtocolMethod( + node: FunctionDeclSyntax, + protocolName: String, + namespace: [String]? + ) -> ExportedFunction? { + let name = node.name.text + + let parameters = parseParameters(from: node.signature.parameterClause, allowDefaults: false) + + let returnType: BridgeType + if let returnClause = node.signature.returnClause { + let resolvedType = withLookupErrors { self.parent.lookupType(for: returnClause.type, errors: &$0) } + + if let type = resolvedType, case .nullable(let wrappedType, _) = type, wrappedType.isOptional { + diagnoseNestedOptional(node: returnClause.type, type: returnClause.type.trimmedDescription) + return nil + } + + guard let type = resolvedType else { return nil } + returnType = type + } else { + returnType = .void + } + + let abiName = ABINameGenerator.generateABIName( + baseName: name, + namespace: namespace, + className: protocolName + ) + + guard let effects = collectEffects(signature: node.signature) else { + return nil + } + + return ExportedFunction( + name: name, + abiName: abiName, + parameters: parameters, + returnType: returnType, + effects: effects, + namespace: namespace, + staticContext: nil + ) + } + + private func visitProtocolProperty( + node: VariableDeclSyntax, + protocolName: String, + protocolKey: String + ) -> SyntaxVisitorContinueKind { + for binding in node.bindings { + guard let pattern = binding.pattern.as(IdentifierPatternSyntax.self) else { + diagnose(node: binding.pattern, message: "Complex patterns not supported for protocol properties") + continue + } + + let propertyName = pattern.identifier.text + + guard let typeAnnotation = binding.typeAnnotation else { + diagnose(node: binding, message: "Protocol property must have explicit type annotation") + continue + } + + guard let propertyType = withLookupErrors({ self.parent.lookupType(for: typeAnnotation.type, errors: &$0) }) + else { + continue + } + + guard let accessorBlock = binding.accessorBlock else { + diagnose( + node: binding, + message: "Protocol property must specify { get } or { get set }", + hint: "Add { get } for readonly or { get set } for readwrite property" + ) + continue + } + + let isReadonly = hasOnlyGetter(accessorBlock) + + let exportedProperty = ExportedProtocolProperty( + name: propertyName, + type: propertyType, + isReadonly: isReadonly + ) + + if var currentProtocol = exportedProtocolByName[protocolKey] { + var properties = currentProtocol.properties + properties.append(exportedProperty) + + currentProtocol = ExportedProtocol( + name: currentProtocol.name, + methods: currentProtocol.methods, + properties: properties, + namespace: currentProtocol.namespace + ) + exportedProtocolByName[protocolKey] = currentProtocol + } + } + + return .skipChildren + } + + private func hasOnlyGetter(_ accessorBlock: AccessorBlockSyntax?) -> Bool { + switch accessorBlock?.accessors { + case .accessors(let accessors): + // Has accessors - check if it only has a getter (no setter, willSet, or didSet) + return !accessors.contains(where: { accessor in + let tokenKind = accessor.accessorSpecifier.tokenKind + return tokenKind == .keyword(.set) || tokenKind == .keyword(.willSet) + || tokenKind == .keyword(.didSet) + }) + case .getter: + // Has only a getter block + return true + case nil: + // No accessor block - this is a stored property, not readonly + return false + } + } + + override func visit(_ node: EnumCaseDeclSyntax) -> SyntaxVisitorContinueKind { + guard case .enumBody(_, let enumKey) = stateStack.current else { + return .visitChildren + } + + for element in node.elements { + let caseName = element.name.text + let rawValue: String? + var associatedValues: [AssociatedValue] = [] + + if exportedEnumByName[enumKey]?.rawType != nil { + if let stringLiteral = element.rawValue?.value.as(StringLiteralExprSyntax.self) { + rawValue = stringLiteral.segments.first?.as(StringSegmentSyntax.self)?.content.text + } else if let boolLiteral = element.rawValue?.value.as(BooleanLiteralExprSyntax.self) { + rawValue = boolLiteral.literal.text + } else { + var numericExpr = element.rawValue?.value + var isNegative = false + + // Check for prefix operator (for negative numbers) + if let prefixExpr = numericExpr?.as(PrefixOperatorExprSyntax.self), + prefixExpr.operator.text == "-" + { + numericExpr = prefixExpr.expression + isNegative = true + } + + if let intLiteral = numericExpr?.as(IntegerLiteralExprSyntax.self) { + rawValue = isNegative ? "-\(intLiteral.literal.text)" : intLiteral.literal.text + } else if let floatLiteral = numericExpr?.as(FloatLiteralExprSyntax.self) { + rawValue = isNegative ? "-\(floatLiteral.literal.text)" : floatLiteral.literal.text + } else { + rawValue = nil + } + } + } else { + rawValue = nil + } + if let parameterClause = element.parameterClause { + for param in parameterClause.parameters { + guard let bridgeType = withLookupErrors({ parent.lookupType(for: param.type, errors: &$0) }) else { + continue + } + + let label = param.firstName?.text + associatedValues.append(AssociatedValue(label: label, type: bridgeType)) + } + } + let enumCase = EnumCase( + name: caseName, + rawValue: rawValue, + associatedValues: associatedValues + ) + exportedEnumByName[enumKey]?.cases.append(enumCase) + } + + return .visitChildren + } + + /// Computes namespace by walking up the AST hierarchy to find parent namespace enums + /// If parent enum is a namespace enum (no cases) then it will be used as part of namespace for given node + /// + /// + /// Method allows for explicit namespace for top level enum, it will be used as base namespace and will concat enum name + private func computeNamespace(for node: some SyntaxProtocol) -> [String]? { + var namespace: [String] = [] + var currentNode: Syntax? = node.parent + + while let parent = currentNode { + if let enumDecl = parent.as(EnumDeclSyntax.self), + enumDecl.attributes.hasJSAttribute() + { + let isNamespaceEnum = !enumDecl.memberBlock.members.contains { member in + member.decl.is(EnumCaseDeclSyntax.self) + } + if isNamespaceEnum { + namespace.insert(enumDecl.name.text, at: 0) + + if let jsAttribute = enumDecl.attributes.firstJSAttribute, + let explicitNamespace = extractNamespace(from: jsAttribute) + { + namespace = explicitNamespace + namespace + break + } + } + } + currentNode = parent.parent + } + + return namespace.isEmpty ? nil : namespace + } + + /// Requires the node to have at least internal access control. + private func computeExplicitAtLeastInternalAccessControl( + for node: some WithModifiersSyntax, + message: String + ) -> String? { + guard let accessControl = node.explicitAccessControl else { + return nil + } + guard accessControl.isAtLeastInternal else { + diagnose( + node: accessControl, + message: message, + hint: "Use `internal`, `package` or `public` access control" + ) + return nil + } + return accessControl.name.text + } +} + +fileprivate extension BridgeType { + /// Returns true if a value of `expectedType` can be assigned to this type. + func isCompatibleWith(_ expectedType: BridgeType) -> Bool { + switch (self, expectedType) { + case let (lhs, rhs) where lhs == rhs: + return true + case (.nullable(let wrapped, _), expectedType): + return wrapped == expectedType + default: + return false + } + } +} + +import SwiftSyntax +#if canImport(BridgeJSSkeleton) +import BridgeJSSkeleton +#endif +#if canImport(BridgeJSUtilities) +import BridgeJSUtilities +#endif + +private final class ImportSwiftMacrosJSImportTypeNameCollector: SyntaxAnyVisitor { + var typeNames: Set = [] + + private func visitTypeDecl(_ attributes: AttributeListSyntax?, _ name: String) -> SyntaxVisitorContinueKind { + if ImportSwiftMacrosAPICollector.AttributeChecker.hasJSClassAttribute(attributes) { + typeNames.insert(name) + } + return .visitChildren + } + + override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { + visitTypeDecl(node.attributes, node.name.text) + } + + override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { + visitTypeDecl(node.attributes, node.name.text) + } +} + +private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { + var importedFunctions: [ImportedFunctionSkeleton] = [] + var importedTypes: [ImportedTypeSkeleton] = [] + var importedGlobalGetters: [ImportedGetterSkeleton] = [] + var errors: [DiagnosticError] = [] + + private let inputFilePath: String + private var jsClassNames: Set + private let parent: SwiftToSkeleton + // MARK: - State Management + + enum State { + case topLevel + case jsClassBody(name: String) + } + + private var stateStack: [State] = [.topLevel] + var state: State { + return stateStack.last! + } + + // 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 staticMethods: [ImportedFunctionSkeleton] + var getters: [ImportedGetterSkeleton] + var setters: [ImportedSetterSkeleton] + } + private var currentType: CurrentType? + + // MARK: - Attribute Checking + + /// Helper struct for checking and extracting attributes + fileprivate struct AttributeChecker { + static func hasJSFunctionAttribute(_ attributes: AttributeListSyntax?) -> Bool { + hasAttribute(attributes, name: "JSFunction") + } + + static func firstJSFunctionAttribute(_ attributes: AttributeListSyntax?) -> AttributeSyntax? { + firstAttribute(attributes, named: "JSFunction") + } + + static func hasJSGetterAttribute(_ attributes: AttributeListSyntax?) -> Bool { + hasAttribute(attributes, name: "JSGetter") + } + + static func firstJSGetterAttribute(_ attributes: AttributeListSyntax?) -> AttributeSyntax? { + firstAttribute(attributes, named: "JSGetter") + } + + static func hasJSSetterAttribute(_ attributes: AttributeListSyntax?) -> Bool { + hasAttribute(attributes, name: "JSSetter") + } + + static func firstJSSetterAttribute(_ attributes: AttributeListSyntax?) -> AttributeSyntax? { + firstAttribute(attributes, named: "JSSetter") + } + + static func hasJSClassAttribute(_ attributes: AttributeListSyntax?) -> Bool { + hasAttribute(attributes, name: "JSClass") + } + + static func firstJSClassAttribute(_ attributes: AttributeListSyntax?) -> AttributeSyntax? { + firstAttribute(attributes, named: "JSClass") + } + + static func firstAttribute(_ attributes: AttributeListSyntax?, named name: String) -> AttributeSyntax? { + attributes?.first { $0.as(AttributeSyntax.self)?.attributeNameText == name }?.as(AttributeSyntax.self) + } + + static func hasAttribute(_ attributes: AttributeListSyntax?, name: String) -> Bool { + guard let attributes else { return false } + return attributes.contains { attribute in + guard let syntax = attribute.as(AttributeSyntax.self) else { return false } + return syntax.attributeNameText == name + } + } + + /// 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 + } + for argument in arguments { + if argument.label?.text == "jsName", + let stringLiteral = argument.expression.as(StringLiteralExprSyntax.self), + let segment = stringLiteral.segments.first?.as(StringSegmentSyntax.self) + { + return segment.content.text + } + } + 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 + + /// Common validation result for setter functions + private struct SetterValidationResult { + let effects: Effects + let jsName: String? + let firstParam: FunctionParameterSyntax + let valueType: BridgeType + } + + /// Validates effects (throws required, async not supported) + private func validateEffects( + _ effects: FunctionEffectSpecifiersSyntax?, + node: some SyntaxProtocol, + attributeName: String + ) -> Effects? { + guard let effects = parseEffects(effects) else { + errors.append( + DiagnosticError( + node: node, + message: "@\(attributeName) declarations must be throws.", + hint: "Declare the function as 'throws(JSException)'." + ) + ) + return nil + } + if effects.isAsync { + errors.append( + DiagnosticError( + node: node, + message: "@\(attributeName) declarations do not support async yet." + ) + ) + return nil + } + return effects + } + + /// Validates a setter function and extracts common information + private func validateSetter(_ node: FunctionDeclSyntax, jsSetter: AttributeSyntax) -> SetterValidationResult? { + guard let effects = validateEffects(node.signature.effectSpecifiers, node: node, attributeName: "JSSetter") + else { + return nil + } + + let jsName = AttributeChecker.extractJSName(from: jsSetter) + let parameters = node.signature.parameterClause.parameters + + guard let firstParam = parameters.first else { + errors.append( + DiagnosticError( + node: node, + message: "@JSSetter function must have at least one parameter." + ) + ) + return nil + } + + if firstParam.type.is(MissingTypeSyntax.self) { + errors.append( + DiagnosticError( + node: firstParam, + message: "All @JSSetter parameters must have explicit types." + ) + ) + return nil + } + + guard let valueType = withLookupErrors({ parent.lookupType(for: firstParam.type, errors: &$0) }) else { + return nil + } + + return SetterValidationResult( + effects: effects, + jsName: jsName, + firstParam: firstParam, + valueType: valueType + ) + } + + // MARK: - Property Name Resolution + + /// Helper for resolving property names from setter function names. + private struct PropertyNameResolver { + /// 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, + normalizeIdentifier: (String) -> String + ) -> (propertyName: String, functionBaseName: String)? { + let rawFunctionName = + functionName.hasPrefix("`") && functionName.hasSuffix("`") && functionName.count > 2 + ? String(functionName.dropFirst().dropLast()) + : functionName + + guard rawFunctionName.hasPrefix("set"), rawFunctionName.count > 3 else { + return nil + } + + let derivedPropertyName = String(rawFunctionName.dropFirst(3)) + let normalized = normalizeIdentifier(derivedPropertyName) + let propertyName = normalized.prefix(1).lowercased() + normalized.dropFirst() + return (propertyName: propertyName, functionBaseName: propertyName) + } + } + + init(inputFilePath: String, knownJSClassNames: Set, parent: SwiftToSkeleton) { + self.inputFilePath = inputFilePath + self.jsClassNames = knownJSClassNames + self.parent = parent + super.init(viewMode: .sourceAccurate) + } + + private func withLookupErrors(_ body: (inout [DiagnosticError]) -> T) -> T { + var errs = self.errors + defer { self.errors = errs } + return body(&errs) + } + + private func enterJSClass(_ typeName: String) { + stateStack.append(.jsClassBody(name: typeName)) + currentType = CurrentType( + name: typeName, + jsName: nil, + from: nil, + constructor: nil, + methods: [], + staticMethods: [], + 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: [], + staticMethods: [], + getters: [], + setters: [] + ) + } + + private func exitJSClass() { + if case .jsClassBody(let typeName) = state, let type = currentType, type.name == typeName { + importedTypes.append( + ImportedTypeSkeleton( + name: type.name, + jsName: type.jsName, + from: type.from, + constructor: type.constructor, + methods: type.methods, + staticMethods: type.staticMethods, + getters: type.getters, + setters: type.setters, + documentation: nil + ) + ) + currentType = nil + } + stateStack.removeLast() + } + + override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { + if AttributeChecker.hasJSClassAttribute(node.attributes) { + 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 + } + + override func visitPost(_ node: StructDeclSyntax) { + if AttributeChecker.hasJSClassAttribute(node.attributes) { + exitJSClass() + } + } + + override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { + if AttributeChecker.hasJSClassAttribute(node.attributes) { + 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 + } + + override func visitPost(_ node: ClassDeclSyntax) { + if AttributeChecker.hasJSClassAttribute(node.attributes) { + exitJSClass() + } + } + + // MARK: - Visitor Methods + + override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind { + switch state { + case .topLevel: + return handleTopLevelFunction(node) + + case .jsClassBody(let typeName): + guard var type = currentType, type.name == typeName else { + return .skipChildren + } + let isStaticMember = isStatic(node.modifiers) + let handled = handleClassFunction(node, typeName: typeName, isStaticMember: isStaticMember, type: &type) + if handled { + currentType = type + } + return .skipChildren + } + } + + private func handleTopLevelFunction(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind { + if let jsFunction = AttributeChecker.firstJSFunctionAttribute(node.attributes), + let function = parseFunction(jsFunction, node) + { + importedFunctions.append(function) + return .skipChildren + } + // Top-level setters are not supported + if AttributeChecker.hasJSSetterAttribute(node.attributes) { + errors.append( + DiagnosticError( + node: node, + message: "@JSSetter is not supported at top-level. Use it only in @JSClass types." + ) + ) + return .skipChildren + } + return .visitChildren + } + + private func handleClassFunction( + _ node: FunctionDeclSyntax, + typeName: String, + isStaticMember: Bool, + type: inout CurrentType + ) -> Bool { + if let jsFunction = AttributeChecker.firstJSFunctionAttribute(node.attributes) { + if let method = parseFunction(jsFunction, node) { + if isStaticMember { + type.staticMethods.append(method) + } else { + type.methods.append(method) + } + } + return true + } + + if AttributeChecker.hasJSSetterAttribute(node.attributes) { + if isStaticMember { + errors.append( + DiagnosticError( + node: node, + message: + "@JSSetter is not supported for static members. Use it only for instance members in @JSClass types." + ) + ) + } else if let jsSetter = AttributeChecker.firstJSSetterAttribute(node.attributes), + let setter = parseSetterSkeleton(jsSetter, node) + { + type.setters.append(setter) + } + return true + } + + return false + } + + override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind { + 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(jsGetter, node) { + importedGlobalGetters.append(getter) + } + return .skipChildren + + case .jsClassBody(let typeName): + guard var type = currentType, type.name == typeName else { + return .skipChildren + } + if isStatic(node.modifiers) { + errors.append( + DiagnosticError( + node: node, + message: + "@JSGetter is not supported for static members. Use it only for instance members in @JSClass types." + ) + ) + } else if let getter = parseGetterSkeleton(jsGetter, node) { + type.getters.append(getter) + currentType = type + } + return .skipChildren + } + } + + override func visit(_ node: InitializerDeclSyntax) -> SyntaxVisitorContinueKind { + guard AttributeChecker.hasJSFunctionAttribute(node.attributes) else { + return .visitChildren + } + + switch state { + case .topLevel: + return .visitChildren + + case .jsClassBody(let typeName): + guard var type = currentType, type.name == typeName else { + return .skipChildren + } + if type.constructor != nil { + errors.append( + DiagnosticError( + node: node, + message: "Only one @JSFunction initializer is supported in @JSClass types." + ) + ) + return .skipChildren + } + if let parsed = parseConstructor(node, typeName: typeName) { + type.constructor = parsed + currentType = type + } + return .skipChildren + } + } + + // MARK: - Parsing Methods + + private func parseConstructor( + _ initializer: InitializerDeclSyntax, + typeName: String + ) -> ImportedConstructorSkeleton? { + guard + validateEffects(initializer.signature.effectSpecifiers, node: initializer, attributeName: "JSFunction") + != nil + else { + return nil + } + return ImportedConstructorSkeleton( + parameters: parseParameters(from: initializer.signature.parameterClause) + ) + } + + private func parseFunction( + _ jsFunction: AttributeSyntax, + _ node: FunctionDeclSyntax, + ) -> ImportedFunctionSkeleton? { + guard validateEffects(node.signature.effectSpecifiers, node: node, attributeName: "JSFunction") != nil + else { + return nil + } + + let baseName = SwiftToSkeleton.normalizeIdentifier(node.name.text) + let jsName = AttributeChecker.extractJSName(from: jsFunction) + let from = AttributeChecker.extractJSImportFrom(from: jsFunction) + let name = baseName + + let parameters = parseParameters(from: node.signature.parameterClause) + let returnType: BridgeType + if let returnTypeSyntax = node.signature.returnClause?.type { + guard let resolved = withLookupErrors({ parent.lookupType(for: returnTypeSyntax, errors: &$0) }) else { + return nil + } + returnType = resolved + } else { + returnType = .void + } + return ImportedFunctionSkeleton( + name: name, + jsName: jsName, + from: from, + parameters: parameters, + returnType: returnType, + documentation: nil + ) + } + + /// Extracts property info from a VariableDeclSyntax (binding, identifier, type) + private func extractPropertyInfo( + _ node: VariableDeclSyntax, + errorMessage: String = "@JSGetter must declare a single stored property with an explicit type." + ) -> (identifier: IdentifierPatternSyntax, type: TypeSyntax)? { + guard let binding = node.bindings.first, + let identifier = binding.pattern.as(IdentifierPatternSyntax.self), + let typeAnnotation = binding.typeAnnotation + else { + errors.append(DiagnosticError(node: node, message: errorMessage)) + return nil + } + return (identifier, typeAnnotation.type) + } + + private func parseGetterSkeleton( + _ jsGetter: AttributeSyntax, + _ node: VariableDeclSyntax + ) -> ImportedGetterSkeleton? { + guard let (identifier, type) = extractPropertyInfo(node) else { + return nil + } + guard let propertyType = withLookupErrors({ parent.lookupType(for: type, errors: &$0) }) else { + 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 + ) + } + + /// Parses a setter as part of a type's property system (for instance setters) + private func parseSetterSkeleton( + _ jsSetter: AttributeSyntax, + _ node: FunctionDeclSyntax + ) -> ImportedSetterSkeleton? { + guard let validation = validateSetter(node, jsSetter: jsSetter) else { + return nil + } + + let functionName = node.name.text + guard + let (propertyName, functionBaseName) = PropertyNameResolver.resolve( + functionName: functionName, + normalizeIdentifier: SwiftToSkeleton.normalizeIdentifier + ) + else { + return nil + } + + return ImportedSetterSkeleton( + name: propertyName, + jsName: validation.jsName, + type: validation.valueType, + documentation: nil, + functionName: "\(functionBaseName)_set" + ) + } + + // MARK: - Type and Parameter Parsing + + private func parseParameters(from clause: FunctionParameterClauseSyntax) -> [Parameter] { + clause.parameters.compactMap { param in + let type = param.type + if type.is(MissingTypeSyntax.self) { + errors.append( + DiagnosticError( + node: param, + message: "All @JSFunction parameters must have explicit types." + ) + ) + return nil + } + guard let bridgeType = withLookupErrors({ parent.lookupType(for: type, errors: &$0) }) else { + return nil + } + let nameToken = param.secondName ?? param.firstName + let name = SwiftToSkeleton.normalizeIdentifier(nameToken.text) + let labelToken = param.secondName == nil ? nil : param.firstName + let label = labelToken?.text == "_" ? nil : labelToken?.text + return Parameter(label: label, name: name, type: bridgeType) + } + } + + // MARK: - Helper Methods + + private func parseEffects(_ effects: FunctionEffectSpecifiersSyntax?) -> Effects? { + let isThrows = effects?.throwsClause != nil + let isAsync = effects?.asyncSpecifier != nil + guard isThrows else { + return nil + } + return Effects(isAsync: isAsync, isThrows: isThrows) + } + + private func isStatic(_ modifiers: DeclModifierListSyntax?) -> Bool { + guard let modifiers else { return false } + return modifiers.contains { modifier in + modifier.name.tokenKind == .keyword(.static) || modifier.name.tokenKind == .keyword(.class) + } + } +} + +extension GenericArgumentListSyntax { + /// Compatibility helper for accessing the first argument as a TypeSyntax + /// + /// Note: SwiftSyntax 601 and later support InlineArrayTypeSyntax and + /// ``GenericArgumentSyntax/argument`` is now a ``TypeSyntax`` or ``ExprSyntax``. + fileprivate var firstAsTypeSyntax: TypeSyntax? { + guard let first = self.first else { return nil } + #if canImport(SwiftSyntax601) + return first.argument.as(TypeSyntax.self) + #else + return TypeSyntax(first.argument) + #endif + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/TypeDeclResolver.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/TypeDeclResolver.swift index a7b183af7..975c0c9dc 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/TypeDeclResolver.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/TypeDeclResolver.swift @@ -8,6 +8,7 @@ class TypeDeclResolver { /// `Outer.Inner` type declaration is represented as ["Outer", "Inner"] typealias QualifiedName = [String] private var typeDeclByQualifiedName: [QualifiedName: TypeDecl] = [:] + private var typeAliasByQualifiedName: [QualifiedName: TypeAliasDeclSyntax] = [:] enum Error: Swift.Error { case typeNotFound(QualifiedName) @@ -62,6 +63,19 @@ class TypeDeclResolver { override func visitPost(_ node: EnumDeclSyntax) { visitPostNominalDecl() } + override func visit(_ node: ProtocolDeclSyntax) -> SyntaxVisitorContinueKind { + return visitNominalDecl(node) + } + override func visitPost(_ node: ProtocolDeclSyntax) { + visitPostNominalDecl() + } + + override func visit(_ node: TypeAliasDeclSyntax) -> SyntaxVisitorContinueKind { + let name = node.name.text + let qualifiedName = scope.map(\.name.text) + [name] + resolver.typeAliasByQualifiedName[qualifiedName] = node + return .skipChildren + } } /// Collects type declarations from a parsed Swift source file @@ -109,4 +123,52 @@ class TypeDeclResolver { func lookupType(fullyQualified: QualifiedName) -> TypeDecl? { return typeDeclByQualifiedName[fullyQualified] } + + /// Resolves a type usage node to the corresponding nominal type declaration collected in this resolver. + /// + /// Supported inputs: + /// - IdentifierTypeSyntax (e.g. `Method`) — resolved relative to the lexical scope, preferring the innermost enclosing type. + /// - MemberTypeSyntax (e.g. `Networking.API.Method`) — resolved by recursively building the fully qualified name. + /// + /// Resolution strategy: + /// 1. If the node is IdentifierTypeSyntax, call `lookupType(for:)` which attempts scope-aware qualification via `tryQualify`. + /// 2. Otherwise, attempt to build a fully qualified name with `qualifiedComponents(from:)` and look it up with `lookupType(fullyQualified:)`. + /// + /// - Parameter type: The SwiftSyntax node representing a type appearance in source code. + /// - Returns: The nominal declaration (enum/class/actor/struct) if found, otherwise nil. + func resolve(_ type: TypeSyntax) -> TypeDecl? { + if let id = type.as(IdentifierTypeSyntax.self) { + return lookupType(for: id) + } + if let components = qualifiedComponents(from: type) { + return lookupType(fullyQualified: components) + } + return nil + } + + /// Resolves a type usage node to a type alias declaration + /// + /// - Parameter type: The SwiftSyntax node representing a type appearance in source code. + /// - Returns: The type alias declaration if found, otherwise nil. + func resolveTypeAlias(_ type: TypeSyntax) -> TypeAliasDeclSyntax? { + if let id = type.as(IdentifierTypeSyntax.self) { + let qualifiedName = tryQualify(type: id) + return typeAliasByQualifiedName[qualifiedName] + } + if let components = qualifiedComponents(from: type) { + return typeAliasByQualifiedName[components] + } + return nil + } + + private func qualifiedComponents(from type: TypeSyntax) -> QualifiedName? { + if let m = type.as(MemberTypeSyntax.self) { + guard let base = qualifiedComponents(from: TypeSyntax(m.baseType)) else { return nil } + return base + [m.name.text] + } else if let id = type.as(IdentifierTypeSyntax.self) { + return [id.name.text] + } else { + return nil + } + } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index 1483692f1..5bf17256d 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -3,31 +3,41 @@ import struct Foundation.Data #if canImport(BridgeJSSkeleton) import BridgeJSSkeleton #endif +#if canImport(BridgeJSUtilities) +import BridgeJSUtilities +#endif -struct BridgeJSLink { - /// The exported skeletons - var exportedSkeletons: [ExportedSkeleton] = [] - var importedSkeletons: [ImportedModuleSkeleton] = [] +public struct BridgeJSLink { + var skeletons: [BridgeJSSkeleton] = [] let sharedMemory: Bool + private let namespaceBuilder = NamespaceBuilder() + private let intrinsicRegistry = JSIntrinsicRegistry() - init( - exportedSkeletons: [ExportedSkeleton] = [], - importedSkeletons: [ImportedModuleSkeleton] = [], + public init( + skeletons: [BridgeJSSkeleton] = [], sharedMemory: Bool ) { - self.exportedSkeletons = exportedSkeletons - self.importedSkeletons = importedSkeletons + self.skeletons = skeletons self.sharedMemory = sharedMemory } - mutating func addExportedSkeletonFile(data: Data) throws { - let skeleton = try JSONDecoder().decode(ExportedSkeleton.self, from: data) - exportedSkeletons.append(skeleton) - } + mutating func addSkeletonFile(data: Data) throws { + do { + let unified = try JSONDecoder().decode(BridgeJSSkeleton.self, from: data) + skeletons.append(unified) + } catch { + struct SkeletonDecodingError: Error, CustomStringConvertible { + let description: String + } + throw SkeletonDecodingError( + description: """ + Failed to decode skeleton file: \(error) - mutating func addImportedSkeletonFile(data: Data) throws { - let skeletons = try JSONDecoder().decode(ImportedModuleSkeleton.self, from: data) - importedSkeletons.append(skeletons) + This file appears to be in an old format. Please regenerate skeleton files using: + bridge-js generate --module-name --target-dir --output-skeleton ... + """ + ) + } } let swiftHeapObjectClassDts = """ @@ -41,766 +51,3018 @@ struct BridgeJSLink { """ let swiftHeapObjectClassJs = """ + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + /// 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); + const state = { pointer, deinit, hasReleased: false }; obj.pointer = pointer; - obj.hasReleased = false; - obj.deinit = deinit; - obj.registry = new FinalizationRegistry((pointer) => { - deinit(pointer); - }); - obj.registry.register(this, obj.pointer); + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); return obj; } release() { - this.registry.unregister(this); - this.deinit(this.pointer); + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); } } """ - func link() throws -> (outputJs: String, outputDts: String) { + fileprivate struct LinkData { var exportsLines: [String] = [] var classLines: [String] = [] var dtsExportLines: [String] = [] var dtsClassLines: [String] = [] - var namespacedFunctions: [ExportedFunction] = [] - var namespacedClasses: [ExportedClass] = [] + var topLevelTypeLines: [String] = [] + var topLevelDtsTypeLines: [String] = [] + var importObjectBuilders: [ImportObjectBuilder] = [] + var enumStaticAssignments: [String] = [] + var needsImportsObject: Bool = false + } - if exportedSkeletons.contains(where: { $0.classes.count > 0 }) { - classLines.append( + private func collectLinkData() throws -> LinkData { + var data = LinkData() + + // Swift heap object class definitions + if skeletons.contains(where: { $0.exported?.classes.isEmpty == false }) { + data.classLines.append( contentsOf: swiftHeapObjectClassJs.split(separator: "\n", omittingEmptySubsequences: false).map { String($0) } ) - dtsClassLines.append( + data.dtsClassLines.append( contentsOf: swiftHeapObjectClassDts.split(separator: "\n", omittingEmptySubsequences: false).map { String($0) } ) } - for skeleton in exportedSkeletons { + // Process exported skeletons + for unified in skeletons { + guard let skeleton = unified.exported else { continue } + // Process classes for klass in skeleton.classes { - let (jsType, dtsType, dtsExportEntry) = renderExportedClass(klass) - classLines.append(contentsOf: jsType) - exportsLines.append("\(klass.name),") - dtsExportLines.append(contentsOf: dtsExportEntry) - dtsClassLines.append(contentsOf: dtsType) + let (jsType, dtsType, dtsExportEntry) = try renderExportedClass(klass) + data.classLines.append(contentsOf: jsType) - if klass.namespace != nil { - namespacedClasses.append(klass) + if klass.namespace == nil { + data.exportsLines.append("\(klass.name),") + data.dtsExportLines.append(contentsOf: dtsExportEntry) } + + data.dtsClassLines.append(contentsOf: dtsType) } - for function in skeleton.functions { - var (js, dts) = renderExportedFunction(function: function) + // Process enums - collect top-level definitions and export entries + var enumExportEntries: [(js: [String], dts: [String])] = [] + for enumDefinition in skeleton.enums { + let (jsTopLevel, jsExportEntry, dtsType, dtsExportEntry) = try renderExportedEnum(enumDefinition) + + // Add top-level JS const definition + if enumDefinition.enumType != .namespace { + var exportedJsEnum = jsTopLevel + if !exportedJsEnum.isEmpty && exportedJsEnum[0].hasPrefix("const ") { + exportedJsEnum[0] = "export " + exportedJsEnum[0] + } + data.topLevelTypeLines.append(contentsOf: exportedJsEnum) + data.topLevelDtsTypeLines.append(contentsOf: dtsType) + } + + if !jsExportEntry.isEmpty || !dtsExportEntry.isEmpty { + enumExportEntries.append((js: jsExportEntry, dts: dtsExportEntry)) + } + } + + var structExportEntries: [(js: [String], dts: [String])] = [] + for structDefinition in skeleton.structs { + let (jsStruct, dtsType, dtsExportEntry) = try renderExportedStruct(structDefinition) + data.topLevelDtsTypeLines.append(contentsOf: dtsType) + + if structDefinition.namespace == nil && (!jsStruct.isEmpty || !dtsExportEntry.isEmpty) { + structExportEntries.append((js: jsStruct, dts: dtsExportEntry)) + } + } - if function.namespace != nil { - namespacedFunctions.append(function) + // Process functions + for function in skeleton.functions { + if function.namespace == nil { + var (js, dts) = try renderExportedFunction(function: function) + js[0] = "\(function.name): " + js[0] + js[js.count - 1] += "," + data.exportsLines.append(contentsOf: js) + data.dtsExportLines.append(contentsOf: dts) } + } + + for entry in enumExportEntries { + data.exportsLines.append(contentsOf: entry.js) + data.dtsExportLines.append(contentsOf: entry.dts) + } - js[0] = "\(function.name): " + js[0] - js[js.count - 1] += "," - exportsLines.append(contentsOf: js) - dtsExportLines.append(contentsOf: dts) + for entry in structExportEntries { + data.exportsLines.append(contentsOf: entry.js) + data.dtsExportLines.append(contentsOf: entry.dts) } } - var importObjectBuilders: [ImportObjectBuilder] = [] - for skeletonSet in importedSkeletons { - let importObjectBuilder = ImportObjectBuilder(moduleName: skeletonSet.moduleName) - for fileSkeleton in skeletonSet.children { + // Process imported skeletons + for unified in skeletons { + guard let imported = unified.imported else { continue } + 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) } } - importObjectBuilders.append(importObjectBuilder) + data.importObjectBuilders.append(importObjectBuilder) } - let hasNamespacedItems = !namespacedFunctions.isEmpty || !namespacedClasses.isEmpty - - let exportsSection: String - if hasNamespacedItems { - let namespaceSetupCode = renderGlobalNamespace( - namespacedFunctions: namespacedFunctions, - namespacedClasses: namespacedClasses - ) - .map { $0.indent(count: 12) }.joined(separator: "\n") - exportsSection = """ - \(classLines.map { $0.indent(count: 12) }.joined(separator: "\n")) - const exports = { - \(exportsLines.map { $0.indent(count: 16) }.joined(separator: "\n")) - }; - - \(namespaceSetupCode) + for unified in skeletons { + guard let skeleton = unified.exported else { continue } + let moduleName = unified.moduleName + if !skeleton.protocols.isEmpty { + let importObjectBuilder: ImportObjectBuilder + if let existingBuilder = data.importObjectBuilders.first(where: { $0.moduleName == moduleName } + ) { + importObjectBuilder = existingBuilder + } else { + importObjectBuilder = ImportObjectBuilder(moduleName: moduleName) + data.importObjectBuilders.append(importObjectBuilder) + } - return exports; - }, - """ - } else { - exportsSection = """ - \(classLines.map { $0.indent(count: 12) }.joined(separator: "\n")) - return { - \(exportsLines.map { $0.indent(count: 16) }.joined(separator: "\n")) - }; - }, - """ + for proto in skeleton.protocols { + for property in proto.properties { + try renderProtocolProperty( + importObjectBuilder: importObjectBuilder, + protocol: proto, + property: property + ) + } + for method in proto.methods { + try renderProtocolMethod( + importObjectBuilder: importObjectBuilder, + protocol: proto, + method: method + ) + } + } + } } - let outputJs = """ - // 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`. + return data + } - 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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)\(sharedMemory ? ".slice()" : ""); - 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)\(sharedMemory ? ".slice()" : ""); - 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; + private func generateVariableDeclarations() -> [String] { + return [ + "let \(JSGlueVariableScope.reservedInstance);", + "let \(JSGlueVariableScope.reservedMemory);", + "let \(JSGlueVariableScope.reservedSetException);", + "const \(JSGlueVariableScope.reservedTextDecoder) = new TextDecoder(\"utf-8\");", + "const \(JSGlueVariableScope.reservedTextEncoder) = new TextEncoder(\"utf-8\");", + "let \(JSGlueVariableScope.reservedStorageToReturnString);", + "let \(JSGlueVariableScope.reservedStorageToReturnBytes);", + "let \(JSGlueVariableScope.reservedStorageToReturnException);", + "let \(JSGlueVariableScope.reservedStorageToReturnOptionalBool);", + "let \(JSGlueVariableScope.reservedStorageToReturnOptionalInt);", + "let \(JSGlueVariableScope.reservedStorageToReturnOptionalFloat);", + "let \(JSGlueVariableScope.reservedStorageToReturnOptionalDouble);", + "let \(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject);", + "let \(JSGlueVariableScope.reservedStringStack) = [];", + "let \(JSGlueVariableScope.reservedI32Stack) = [];", + "let \(JSGlueVariableScope.reservedF32Stack) = [];", + "let \(JSGlueVariableScope.reservedF64Stack) = [];", + "let \(JSGlueVariableScope.reservedPointerStack) = [];", + "let \(JSGlueVariableScope.reservedTmpStructCleanups) = [];", + "const \(JSGlueVariableScope.reservedEnumHelpers) = {};", + "const \(JSGlueVariableScope.reservedStructHelpers) = {};", + "", + "let _exports = null;", + "let bjs = null;", + ] + } + + private func generateAddImports(needsImportsObject: Bool) throws -> CodeFragmentPrinter { + let printer = CodeFragmentPrinter() + let allStructs = skeletons.compactMap { $0.exported?.structs }.flatMap { $0 } + printer.write("return {") + try printer.indent { + printer.write(lines: [ + "/**", + " * @param {WebAssembly.Imports} importObject", + " */", + "addImports: (importObject, importsContext) => {", + ]) + + try printer.indent { + printer.write(lines: [ + "bjs = {};", + "importObject[\"bjs\"] = bjs;", + ]) + if needsImportsObject { + printer.write(lines: [ + "const imports = options.getImports(importsContext);" + ]) + } + printer.write("bjs[\"swift_js_return_string\"] = function(ptr, len) {") + printer.indent { + printer.write( + "const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr, len)\(sharedMemory ? ".slice()" : "");" + ) + printer.write( + "\(JSGlueVariableScope.reservedStorageToReturnString) = \(JSGlueVariableScope.reservedTextDecoder).decode(bytes);" + ) + } + printer.write("}") + printer.write("bjs[\"swift_js_init_memory\"] = function(sourceId, bytesPtr) {") + printer.indent { + printer.write( + "const source = \(JSGlueVariableScope.reservedSwift).\(JSGlueVariableScope.reservedMemory).getObject(sourceId);" + ) + printer.write( + "\(JSGlueVariableScope.reservedSwift).\(JSGlueVariableScope.reservedMemory).release(sourceId);" + ) + printer.write( + "const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, bytesPtr);" + ) + printer.write("bytes.set(source);") + } + printer.write("}") + printer.write("bjs[\"swift_js_make_js_string\"] = function(ptr, len) {") + printer.indent { + printer.write( + "const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr, len)\(sharedMemory ? ".slice()" : "");" + ) + printer.write( + "return \(JSGlueVariableScope.reservedSwift).\(JSGlueVariableScope.reservedMemory).retain(\(JSGlueVariableScope.reservedTextDecoder).decode(bytes));" + ) + } + printer.write("}") + printer.write("bjs[\"swift_js_init_memory_with_result\"] = function(ptr, len) {") + printer.indent { + printer.write( + "const target = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr, len);" + ) + printer.write("target.set(\(JSGlueVariableScope.reservedStorageToReturnBytes));") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnBytes) = undefined;") + } + printer.write("}") + printer.write("bjs[\"swift_js_throw\"] = function(id) {") + printer.indent { + printer.write( + "\(JSGlueVariableScope.reservedStorageToReturnException) = \(JSGlueVariableScope.reservedSwift).\(JSGlueVariableScope.reservedMemory).retainByRef(id);" + ) + } + printer.write("}") + printer.write("bjs[\"swift_js_retain\"] = function(id) {") + printer.indent { + printer.write( + "return \(JSGlueVariableScope.reservedSwift).\(JSGlueVariableScope.reservedMemory).retainByRef(id);" + ) + } + printer.write("}") + printer.write("bjs[\"swift_js_release\"] = function(id) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(id);") + } + printer.write("}") + printer.write("bjs[\"swift_js_push_i32\"] = function(v) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedI32Stack).push(v | 0);") + } + printer.write("}") + printer.write("bjs[\"swift_js_push_f32\"] = function(v) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedF32Stack).push(Math.fround(v));") + } + printer.write("}") + printer.write("bjs[\"swift_js_push_f64\"] = function(v) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedF64Stack).push(v);") + } + printer.write("}") + printer.write("bjs[\"swift_js_push_string\"] = function(ptr, len) {") + printer.indent { + printer.write( + "const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr, len)\(sharedMemory ? ".slice()" : "");" + ) + printer.write("const value = \(JSGlueVariableScope.reservedTextDecoder).decode(bytes);") + printer.write("\(JSGlueVariableScope.reservedStringStack).push(value);") + } + printer.write("}") + printer.write("bjs[\"swift_js_pop_i32\"] = function() {") + printer.indent { + printer.write("return \(JSGlueVariableScope.reservedI32Stack).pop();") + } + printer.write("}") + printer.write("bjs[\"swift_js_pop_f32\"] = function() {") + printer.indent { + printer.write("return \(JSGlueVariableScope.reservedF32Stack).pop();") + } + printer.write("}") + printer.write("bjs[\"swift_js_pop_f64\"] = function() {") + printer.indent { + printer.write("return \(JSGlueVariableScope.reservedF64Stack).pop();") + } + printer.write("}") + printer.write("bjs[\"swift_js_push_pointer\"] = function(pointer) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedPointerStack).push(pointer);") + } + printer.write("}") + printer.write("bjs[\"swift_js_pop_pointer\"] = function() {") + printer.indent { + printer.write("return \(JSGlueVariableScope.reservedPointerStack).pop();") + } + printer.write("}") + printer.write("bjs[\"swift_js_struct_cleanup\"] = function(cleanupId) {") + printer.indent { + printer.write("if (cleanupId === 0) { return; }") + printer.write("const index = (cleanupId | 0) - 1;") + printer.write("const cleanup = \(JSGlueVariableScope.reservedTmpStructCleanups)[index];") + printer.write("\(JSGlueVariableScope.reservedTmpStructCleanups)[index] = null;") + printer.write("if (cleanup) { cleanup(); }") + printer.write( + "while (\(JSGlueVariableScope.reservedTmpStructCleanups).length > 0 && \(JSGlueVariableScope.reservedTmpStructCleanups)[\(JSGlueVariableScope.reservedTmpStructCleanups).length - 1] == null) {" + ) + printer.indent { + printer.write("\(JSGlueVariableScope.reservedTmpStructCleanups).pop();") + } + printer.write("}") + } + printer.write("}") + + if !allStructs.isEmpty { + for structDef in allStructs { + printer.write("bjs[\"swift_js_struct_lower_\(structDef.name)\"] = function(objectId) {") + printer.indent { + printer.write( + "const { cleanup: cleanup } = \(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lower(\(JSGlueVariableScope.reservedSwift).memory.getObject(objectId));" + ) + printer.write("if (cleanup) {") + printer.indent { + printer.write( + "return \(JSGlueVariableScope.reservedTmpStructCleanups).push(cleanup);" + ) + } + printer.write("}") + printer.write("return 0;") } - bjs["swift_js_throw"] = function(id) { - tmpRetException = swift.memory.retainByRef(id); + printer.write("}") + + printer.write("bjs[\"swift_js_struct_lift_\(structDef.name)\"] = function() {") + printer.indent { + printer.write( + "const value = \(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lift();" + ) + printer.write("return \(JSGlueVariableScope.reservedSwift).memory.retain(value);") } - bjs["swift_js_retain"] = function(id) { - return swift.memory.retainByRef(id); + printer.write("}") + } + } + + printer.write("bjs[\"swift_js_return_optional_bool\"] = function(isSome, value) {") + printer.indent { + printer.write("if (isSome === 0) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalBool) = null;") + } + printer.write("} else {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalBool) = value !== 0;") + } + printer.write("}") + } + printer.write("}") + printer.write("bjs[\"swift_js_return_optional_int\"] = function(isSome, value) {") + printer.indent { + printer.write("if (isSome === 0) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = null;") + } + printer.write("} else {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = value | 0;") + } + printer.write("}") + } + printer.write("}") + printer.write("bjs[\"swift_js_return_optional_float\"] = function(isSome, value) {") + printer.indent { + printer.write("if (isSome === 0) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = null;") + } + printer.write("} else {") + printer.indent { + printer.write( + "\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = Math.fround(value);" + ) + } + printer.write("}") + } + printer.write("}") + printer.write("bjs[\"swift_js_return_optional_double\"] = function(isSome, value) {") + printer.indent { + printer.write("if (isSome === 0) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = null;") + } + printer.write("} else {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = value;") + } + printer.write("}") + } + printer.write("}") + printer.write("bjs[\"swift_js_return_optional_string\"] = function(isSome, ptr, len) {") + printer.indent { + printer.write("if (isSome === 0) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = null;") + } + printer.write("} else {") + printer.indent { + printer.write(lines: [ + "const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr, len);", + "\(JSGlueVariableScope.reservedStorageToReturnString) = \(JSGlueVariableScope.reservedTextDecoder).decode(bytes);", + ]) + } + printer.write("}") + } + printer.write("}") + printer.write("bjs[\"swift_js_return_optional_object\"] = function(isSome, objectId) {") + printer.indent { + printer.write("if (isSome === 0) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = null;") + } + printer.write("} else {") + printer.indent { + printer.write( + "\(JSGlueVariableScope.reservedStorageToReturnString) = \(JSGlueVariableScope.reservedSwift).memory.getObject(objectId);" + ) + } + printer.write("}") + } + printer.write("}") + printer.write("bjs[\"swift_js_return_optional_heap_object\"] = function(isSome, pointer) {") + printer.indent { + printer.write("if (isSome === 0) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject) = null;") + } + printer.write("} else {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject) = pointer;") + } + printer.write("}") + } + printer.write("}") + printer.write("bjs[\"swift_js_get_optional_int_presence\"] = function() {") + printer.indent { + printer.write("return \(JSGlueVariableScope.reservedStorageToReturnOptionalInt) != null ? 1 : 0;") + } + printer.write("}") + printer.write("bjs[\"swift_js_get_optional_int_value\"] = function() {") + printer.indent { + printer.write("const value = \(JSGlueVariableScope.reservedStorageToReturnOptionalInt);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = undefined;") + printer.write("return value;") + } + printer.write("}") + printer.write("bjs[\"swift_js_get_optional_string\"] = function() {") + printer.indent { + printer.write("const str = \(JSGlueVariableScope.reservedStorageToReturnString);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") + printer.write("if (str == null) {") + printer.indent { + printer.write("return -1;") + } + printer.write("} else {") + printer.indent { + printer.write("const bytes = \(JSGlueVariableScope.reservedTextEncoder).encode(str);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnBytes) = bytes;") + printer.write("return bytes.length;") + } + printer.write("}") + } + printer.write("}") + printer.write("bjs[\"swift_js_get_optional_float_presence\"] = function() {") + printer.indent { + printer.write("return \(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) != null ? 1 : 0;") + } + printer.write("}") + printer.write("bjs[\"swift_js_get_optional_float_value\"] = function() {") + printer.indent { + printer.write("const value = \(JSGlueVariableScope.reservedStorageToReturnOptionalFloat);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = undefined;") + printer.write("return value;") + } + printer.write("}") + printer.write("bjs[\"swift_js_get_optional_double_presence\"] = function() {") + printer.indent { + printer.write( + "return \(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) != null ? 1 : 0;" + ) + } + printer.write("}") + printer.write("bjs[\"swift_js_get_optional_double_value\"] = function() {") + printer.indent { + printer.write("const value = \(JSGlueVariableScope.reservedStorageToReturnOptionalDouble);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = undefined;") + printer.write("return value;") + } + printer.write("}") + printer.write("bjs[\"swift_js_get_optional_heap_object_pointer\"] = function() {") + printer.indent { + printer.write("const pointer = \(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject) = undefined;") + printer.write("return pointer || 0;") + } + printer.write("}") + // Always provide swift_js_closure_unregister as a no-op by default. + // The @_extern(wasm) declaration in BridgeJSIntrinsics.swift is unconditional, + // so the WASM binary always imports this symbol. When closures ARE used, + // the real implementation below will override this no-op. + printer.write("bjs[\"swift_js_closure_unregister\"] = function(funcRef) {}") + + for unified in skeletons { + let moduleName = unified.moduleName + let collector = ClosureSignatureCollectorVisitor() + var walker = BridgeTypeWalker(visitor: collector) + walker.walk(unified) + let closureSignatures = walker.visitor.signatures + + guard !closureSignatures.isEmpty else { continue } + + intrinsicRegistry.register(name: "swiftClosureHelpers") { helperPrinter in + helperPrinter.write( + "const \(JSGlueVariableScope.reservedSwiftClosureRegistry) = (typeof FinalizationRegistry === \"undefined\") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => {" + ) + helperPrinter.indent { + helperPrinter.write("if (state.unregistered) { return; }") + helperPrinter.write( + "\(JSGlueVariableScope.reservedInstance)?.exports?.bjs_release_swift_closure(state.pointer);" + ) } - bjs["swift_js_release"] = function(id) { - swift.memory.release(id); + helperPrinter.write("});") + helperPrinter.write( + "const \(JSGlueVariableScope.reservedMakeSwiftClosure) = (pointer, file, line, func) => {" + ) + helperPrinter.indent { + helperPrinter.write( + "const state = { pointer, file, line, unregistered: false };" + ) + helperPrinter.write("const real = (...args) => {") + helperPrinter.indent { + helperPrinter.write("if (state.unregistered) {") + helperPrinter.indent { + helperPrinter.write( + "const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, state.file);" + ) + helperPrinter.write("let length = 0;") + helperPrinter.write("while (bytes[length] !== 0) { length += 1; }") + helperPrinter.write( + "const fileID = \(JSGlueVariableScope.reservedTextDecoder).decode(bytes.subarray(0, length));" + ) + helperPrinter.write( + "throw new Error(`Attempted to call a released JSTypedClosure created at ${fileID}:${state.line}`);" + ) + } + helperPrinter.write("}") + helperPrinter.write("return func(...args);") + } + helperPrinter.write("};") + helperPrinter.write( + "real.__unregister = () => {" + ) + helperPrinter.indent { + helperPrinter.write( + "if (state.unregistered) { return; }" + ) + helperPrinter.write("state.unregistered = true;") + helperPrinter.write( + "\(JSGlueVariableScope.reservedSwiftClosureRegistry).unregister(state);" + ) + } + helperPrinter.write("};") + helperPrinter.write( + "\(JSGlueVariableScope.reservedSwiftClosureRegistry).register(real, state, state);" + ) + helperPrinter.write("return \(JSGlueVariableScope.reservedSwift).memory.retain(real);") } - \(renderSwiftClassWrappers().map { $0.indent(count: 12) }.joined(separator: "\n")) - \(importObjectBuilders.flatMap { $0.importedLines }.map { $0.indent(count: 12) }.joined(separator: "\n")) - }, - setInstance: (i) => { - instance = i; - memory = instance.exports.memory; - setException = (error) => { - instance.exports._swift_js_exception.value = swift.memory.retain(error) + helperPrinter.write("};") + } + printer.write("bjs[\"swift_js_closure_unregister\"] = function(funcRef) {") + printer.indent { + printer.write("const func = \(JSGlueVariableScope.reservedSwift).memory.getObject(funcRef);") + printer.write("func.__unregister();") + } + printer.write("}") + + for signature in closureSignatures.sorted(by: { $0.mangleName < $1.mangleName }) { + let invokeFuncName = "invoke_js_callback_\(moduleName)_\(signature.mangleName)" + let invokeLines = try generateInvokeFunction( + signature: signature, + functionName: invokeFuncName + ) + printer.write(lines: invokeLines) + + let lowerFuncName = "lower_closure_\(moduleName)_\(signature.mangleName)" + let makeFuncName = "make_swift_closure_\(moduleName)_\(signature.mangleName)" + printer.write("bjs[\"\(makeFuncName)\"] = function(boxPtr, file, line) {") + try printer.indent { + let lowerLines = try generateLowerClosureFunction( + signature: signature, + functionName: lowerFuncName + ) + printer.write(lines: lowerLines) + printer.write( + "return \(JSGlueVariableScope.reservedMakeSwiftClosure)(boxPtr, file, line, \(lowerFuncName));" + ) } - }, - /** @param {WebAssembly.Instance} instance */ - createExports: (instance) => { - const js = swift.memory.heap; - \(exportsSection) + printer.write("}") + } } } - """ - - var dtsLines: [String] = [] - dtsLines.append(contentsOf: namespaceDeclarations()) - dtsLines.append(contentsOf: dtsClassLines) - dtsLines.append(contentsOf: generateImportedTypeDefinitions()) - dtsLines.append("export type Exports = {") - dtsLines.append(contentsOf: dtsExportLines.map { $0.indent(count: 4) }) - dtsLines.append("}") - dtsLines.append("export type Imports = {") - dtsLines.append(contentsOf: importObjectBuilders.flatMap { $0.dtsImportLines }.map { $0.indent(count: 4) }) - dtsLines.append("}") - let outputDts = """ - // 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`. + } - \(dtsLines.joined(separator: "\n")) - export function createInstantiator(options: { - imports: Imports; - }, swift: any): Promise<{ - addImports: (importObject: WebAssembly.Imports) => void; - setInstance: (instance: WebAssembly.Instance) => void; - createExports: (instance: WebAssembly.Instance) => Exports; - }>; - """ - return (outputJs, outputDts) + return printer } - private func renderSwiftClassWrappers() -> [String] { - var wrapperLines: [String] = [] - var modulesByName: [String: [ExportedClass]] = [:] + private func generateInvokeFunction( + signature: ClosureSignature, + functionName: String + ) throws -> [String] { + let thunkBuilder = ImportedThunkBuilder(context: .exportSwift, intrinsicRegistry: intrinsicRegistry) + thunkBuilder.parameterNames.append("callbackId") + thunkBuilder.body.write("const callback = \(JSGlueVariableScope.reservedSwift).memory.getObject(callbackId);") + + for (index, paramType) in signature.parameters.enumerated() { + let paramName = "param\(index)" + try thunkBuilder.liftParameter(param: Parameter(label: nil, name: paramName, type: paramType)) + } - // Group classes by their module name - for skeleton in exportedSkeletons { - if skeleton.classes.isEmpty { continue } + let returnExpr = try thunkBuilder.call(calleeExpr: "callback", returnType: signature.returnType) - if modulesByName[skeleton.moduleName] == nil { - modulesByName[skeleton.moduleName] = [] - } - modulesByName[skeleton.moduleName]?.append(contentsOf: skeleton.classes) - } + var functionLines = thunkBuilder.renderFunction( + name: nil, + returnExpr: returnExpr, + returnType: signature.returnType + ) + functionLines[0] = "bjs[\"\(functionName)\"] = " + functionLines[0] - // Generate wrapper functions for each module - for (moduleName, classes) in modulesByName { - wrapperLines.append("// Wrapper functions for module: \(moduleName)") - wrapperLines.append("if (!importObject[\"\(moduleName)\"]) {") - wrapperLines.append(" importObject[\"\(moduleName)\"] = {};") - wrapperLines.append("}") + return functionLines + } - for klass in classes { - let wrapperFunctionName = "bjs_\(klass.name)_wrap" - wrapperLines.append("importObject[\"\(moduleName)\"][\"\(wrapperFunctionName)\"] = function(pointer) {") - wrapperLines.append(" const obj = \(klass.name).__construct(pointer);") - wrapperLines.append(" return swift.memory.retain(obj);") - wrapperLines.append("};") + /// Generates a lower_closure_* function that wraps a Swift closure for JavaScript + private func generateLowerClosureFunction( + signature: ClosureSignature, + functionName: String + ) throws -> [String] { + let printer = CodeFragmentPrinter() + let builder = ExportedThunkBuilder( + effects: Effects(isAsync: false, isThrows: true), + hasDirectAccessToSwiftClass: false, + intrinsicRegistry: intrinsicRegistry + ) + builder.parameterForwardings.append("boxPtr") + + printer.write( + "const \(functionName) = function(\(signature.parameters.indices.map { "param\($0)" }.joined(separator: ", "))) {" + ) + try printer.indent { + // Lower parameters using shared thunk builder + for (index, paramType) in signature.parameters.enumerated() { + let paramName = "param\(index)" + try builder.lowerParameter(param: Parameter(label: nil, name: paramName, type: paramType)) } + + let invokeCall = + "invoke_swift_closure_\(signature.moduleName)_\(signature.mangleName)" + let returnExpr = try builder.call(abiName: invokeCall, returnType: signature.returnType) + builder.renderFunctionBody(into: printer, returnExpr: returnExpr) } + printer.write("};") - return wrapperLines + return printer.lines } - private func generateImportedTypeDefinitions() -> [String] { - var typeDefinitions: [String] = [] + private func generateTypeScript(data: LinkData) -> String { + let header = """ + // 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`. + """ + let printer = CodeFragmentPrinter(header: header) + printer.nextLine() - for skeletonSet in importedSkeletons { - for fileSkeleton in skeletonSet.children { - for type in fileSkeleton.types { - typeDefinitions.append("export interface \(type.name) {") + let exportedSkeletons = skeletons.compactMap(\.exported) - // Add methods - for method in type.methods { - let methodSignature = - "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: Effects(isAsync: false, isThrows: false)));" - typeDefinitions.append(methodSignature.indent(count: 4)) + for skeleton in exportedSkeletons { + for proto in skeleton.protocols { + printer.write("export interface \(proto.name) {") + printer.indent { + for method in proto.methods { + printer.write( + "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));" + ) } - - // Add properties - for property in type.properties { + for property in proto.properties { let propertySignature = property.isReadonly - ? "readonly \(property.name): \(property.type.tsType);" - : "\(property.name): \(property.type.tsType);" - typeDefinitions.append(propertySignature.indent(count: 4)) + ? "readonly \(property.name): \(resolveTypeScriptType(property.type));" + : "\(property.name): \(resolveTypeScriptType(property.type));" + printer.write(propertySignature) } - - typeDefinitions.append("}") } + printer.write("}") + printer.nextLine() } } - return typeDefinitions - } - - private func namespaceDeclarations() -> [String] { - var dtsLines: [String] = [] - var namespaceFunctions: [String: [ExportedFunction]] = [:] - var namespaceClasses: [String: [ExportedClass]] = [:] + printer.write(lines: data.topLevelDtsTypeLines) + // Generate Object types for const-style enums for skeleton in exportedSkeletons { - for function in skeleton.functions { - if let namespace = function.namespace { - let namespaceKey = namespace.joined(separator: ".") - if namespaceFunctions[namespaceKey] == nil { - namespaceFunctions[namespaceKey] = [] + for enumDefinition in skeleton.enums + where enumDefinition.enumType != .namespace && enumDefinition.emitStyle != .tsEnum { + let enumValuesName = enumDefinition.valuesName + let enumObjectName = enumDefinition.objectTypeName + + // Use fully-qualified path for namespaced enums + let fullEnumValuesPath: String + if let namespace = enumDefinition.namespace, !namespace.isEmpty { + fullEnumValuesPath = namespace.joined(separator: ".") + "." + enumValuesName + } else { + fullEnumValuesPath = enumValuesName + } + + if !enumDefinition.staticMethods.isEmpty || !enumDefinition.staticProperties.isEmpty { + printer.write("export type \(enumObjectName) = typeof \(fullEnumValuesPath) & {") + printer.indent { + for function in enumDefinition.staticMethods { + printer.write( + "\(function.name)\(renderTSSignature(parameters: function.parameters, returnType: function.returnType, effects: function.effects));" + ) + } + for property in enumDefinition.staticProperties { + let readonly = property.isReadonly ? "readonly " : "" + printer.write("\(readonly)\(property.name): \(resolveTypeScriptType(property.type));") + } } - namespaceFunctions[namespaceKey]?.append(function) + printer.write("};") + } else { + printer.write("export type \(enumObjectName) = typeof \(fullEnumValuesPath);") } + printer.nextLine() } + } - for klass in skeleton.classes { - if let classNamespace = klass.namespace { - let namespaceKey = classNamespace.joined(separator: ".") - if namespaceClasses[namespaceKey] == nil { - namespaceClasses[namespaceKey] = [] + // Type definitions section (namespace declarations, class definitions, imported types) + let namespaceDeclarationsLines = namespaceBuilder.namespaceDeclarations( + exportedSkeletons: exportedSkeletons, + renderTSSignatureCallback: { parameters, returnType, effects in + self.renderTSSignature(parameters: parameters, returnType: returnType, effects: effects) + } + ) + printer.write(lines: namespaceDeclarationsLines) + + printer.write(lines: data.dtsClassLines) + + // Imported type definitions + printer.write(lines: generateImportedTypeDefinitions()) + + // Exports type + printer.write("export type Exports = {") + printer.indent { + // Add non-namespaced items + printer.write(lines: data.dtsExportLines) + + // Add hierarchical namespaced items + let hierarchicalLines = namespaceBuilder.buildHierarchicalExportsType( + exportedSkeletons: exportedSkeletons, + renderClassEntry: { klass in + let printer = CodeFragmentPrinter() + printer.write("\(klass.name): {") + printer.indent { + if let constructor = klass.constructor { + printer.write( + "new\(self.renderTSSignature(parameters: constructor.parameters, returnType: .swiftHeapObject(klass.name), effects: constructor.effects));" + ) + } } - namespaceClasses[namespaceKey]?.append(klass) + printer.write("}") + return printer.lines + }, + renderFunctionSignature: { function in + "\(function.name)\(self.renderTSSignature(parameters: function.parameters, returnType: function.returnType, effects: function.effects));" } - } + ) + printer.write(lines: hierarchicalLines) } + printer.write("}") - guard !namespaceFunctions.isEmpty || !namespaceClasses.isEmpty else { return dtsLines } + // Imports type + printer.write("export type Imports = {") + printer.indent { + printer.write(lines: data.importObjectBuilders.flatMap { $0.dtsImportLines }) + } + printer.write("}") - dtsLines.append("export {};") - dtsLines.append("") - dtsLines.append("declare global {") + // Function signature section + printer.write("export function createInstantiator(options: {") + printer.indent { + printer.write("imports: Imports;") + } + printer.write("}, swift: any): Promise<{") + printer.indent { + printer.write(lines: [ + "addImports: (importObject: WebAssembly.Imports) => void;", + "setInstance: (instance: WebAssembly.Instance) => void;", + "createExports: (instance: WebAssembly.Instance) => Exports;", + ]) + } + printer.write("}>;") - let identBaseSize = 4 + return printer.lines.joined(separator: "\n") + } - for (namespacePath, classes) in namespaceClasses.sorted(by: { $0.key < $1.key }) { - let parts = namespacePath.split(separator: ".").map(String.init) + /// Generates JavaScript output using CodeFragmentPrinter for better maintainability + private func generateJavaScript(data: LinkData) throws -> String { + let header = """ + // 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`. + """ + let printer = CodeFragmentPrinter(header: header) + printer.nextLine() - for i in 0.. {") + printer.indent { + printer.write(lines: [ + "\(JSGlueVariableScope.reservedInstance) = i;", + "\(JSGlueVariableScope.reservedMemory) = \(JSGlueVariableScope.reservedInstance).exports.memory;", + ]) + printer.nextLine() + // Error handling + printer.write("\(JSGlueVariableScope.reservedSetException) = (error) => {") + printer.indent { + printer.write( + "\(JSGlueVariableScope.reservedInstance).exports._swift_js_exception.value = \(JSGlueVariableScope.reservedSwift).memory.retain(error)" + ) + } + printer.write("}") } + printer.write("},") + } - if !namespaceExists { - for i in (0.. {", + ]) + printer.indent { + printer.write("const js = \(JSGlueVariableScope.reservedSwift).memory.heap;") + + printer.write(lines: data.classLines) + + // Struct and enum helpers must be initialized AFTER classes are defined (to allow _exports access) + printer.write(contentsOf: structHelperAssignments()) + printer.write(contentsOf: enumHelperAssignments()) + let namespaceInitCode = namespaceBuilder.buildNamespaceInitialization( + exportedSkeletons: exportedSkeletons + ) + printer.write(lines: namespaceInitCode) + + printer.write(lines: propertyAssignments) } + printer.write("},") } + printer.write("}") + printer.unindent() + printer.write("}") - dtsLines.append("}") - dtsLines.append("") + return printer.lines.joined(separator: "\n") + } - return dtsLines + public func link() throws -> (outputJs: String, outputDts: String) { + intrinsicRegistry.reset() + let data = try collectLinkData() + let outputJs = try generateJavaScript(data: data) + let outputDts = generateTypeScript(data: data) + return (outputJs, outputDts) } - class ExportedThunkBuilder { - var bodyLines: [String] = [] - var cleanupLines: [String] = [] - var parameterForwardings: [String] = [] - let effects: Effects + private func enumHelperAssignments() -> CodeFragmentPrinter { + let printer = CodeFragmentPrinter() - init(effects: Effects) { - self.effects = effects + for skeleton in skeletons.compactMap(\.exported) { + for enumDef in skeleton.enums where enumDef.enumType == .associatedValue { + printer.write( + "const \(enumDef.name)Helpers = __bjs_create\(enumDef.valuesName)Helpers()();" + ) + printer.write("\(JSGlueVariableScope.reservedEnumHelpers).\(enumDef.name) = \(enumDef.name)Helpers;") + printer.nextLine() + } } - func lowerParameter(param: Parameter) { - switch param.type { - case .void: return - case .int, .float, .double, .bool: - parameterForwardings.append(param.name) - case .string: - let bytesLabel = "\(param.name)Bytes" - let bytesIdLabel = "\(param.name)Id" - bodyLines.append("const \(bytesLabel) = textEncoder.encode(\(param.name));") - bodyLines.append("const \(bytesIdLabel) = swift.memory.retain(\(bytesLabel));") - cleanupLines.append("swift.memory.release(\(bytesIdLabel));") - parameterForwardings.append(bytesIdLabel) - parameterForwardings.append("\(bytesLabel).length") - case .jsObject: - parameterForwardings.append("swift.memory.retain(\(param.name))") - case .swiftHeapObject: - parameterForwardings.append("\(param.name).pointer") + return printer + } + + private func structHelperAssignments() -> CodeFragmentPrinter { + let printer = CodeFragmentPrinter() + + for skeleton in skeletons.compactMap(\.exported) { + for structDef in skeleton.structs { + printer.write( + "const \(structDef.name)Helpers = __bjs_create\(structDef.name)Helpers()();" + ) + printer.write( + "\(JSGlueVariableScope.reservedStructHelpers).\(structDef.name) = \(structDef.name)Helpers;" + ) + printer.nextLine() } } - func lowerSelf() { - parameterForwardings.append("this.pointer") - } + return printer + } - func call(abiName: String, returnType: BridgeType) -> String? { - if effects.isAsync { - return _call(abiName: abiName, returnType: .jsObject(nil)) - } else { - return _call(abiName: abiName, returnType: returnType) + private func renderSwiftClassWrappers() -> [String] { + var wrapperLines: [String] = [] + var modulesByName: [String: [ExportedClass]] = [:] + + // Group classes by their module name + for unified in skeletons { + guard let skeleton = unified.exported else { continue } + if skeleton.classes.isEmpty { continue } + let moduleName = unified.moduleName + + if modulesByName[moduleName] == nil { + modulesByName[moduleName] = [] } + modulesByName[moduleName]?.append(contentsOf: skeleton.classes) } - private func _call(abiName: String, returnType: BridgeType) -> String? { - let call = "instance.exports.\(abiName)(\(parameterForwardings.joined(separator: ", ")))" - var returnExpr: String? - - switch returnType { - case .void: - bodyLines.append("\(call);") - case .string: - bodyLines.append("\(call);") - bodyLines.append("const ret = tmpRetString;") - bodyLines.append("tmpRetString = undefined;") - returnExpr = "ret" - case .int, .float, .double: - bodyLines.append("const ret = \(call);") - returnExpr = "ret" - case .bool: - bodyLines.append("const ret = \(call) !== 0;") - returnExpr = "ret" - case .jsObject: - bodyLines.append("const retId = \(call);") - // TODO: Implement "take" operation - bodyLines.append("const ret = swift.memory.getObject(retId);") - bodyLines.append("swift.memory.release(retId);") - returnExpr = "ret" - case .swiftHeapObject(let name): - bodyLines.append("const ret = \(name).__construct(\(call));") - returnExpr = "ret" + // Generate wrapper functions for each module + for (moduleName, classes) in modulesByName.sorted(by: { $0.key < $1.key }) { + wrapperLines.append("// Wrapper functions for module: \(moduleName)") + wrapperLines.append("if (!importObject[\"\(moduleName)\"]) {") + wrapperLines.append(" importObject[\"\(moduleName)\"] = {};") + wrapperLines.append("}") + + for klass in classes.sorted(by: { $0.name < $1.name }) { + let wrapperFunctionName = "bjs_\(klass.name)_wrap" + wrapperLines.append("importObject[\"\(moduleName)\"][\"\(wrapperFunctionName)\"] = function(pointer) {") + wrapperLines.append(" const obj = _exports['\(klass.name)'].__construct(pointer);") + wrapperLines.append(" return \(JSGlueVariableScope.reservedSwift).memory.retain(obj);") + wrapperLines.append("};") } - return returnExpr } - func callConstructor(abiName: String) -> String { - let call = "instance.exports.\(abiName)(\(parameterForwardings.joined(separator: ", ")))" - bodyLines.append("const ret = \(call);") - return "ret" + return wrapperLines + } + + private func generateNamespacePropertyAssignments( + data: LinkData, + exportedSkeletons: [ExportedSkeleton], + namespaceBuilder: NamespaceBuilder + ) throws -> [String] { + let printer = CodeFragmentPrinter() + + // Only include enum static assignments for modules with exposeToGlobal + let hasAnyGlobalExposure = exportedSkeletons.contains { $0.exposeToGlobal } + if hasAnyGlobalExposure { + printer.write(lines: data.enumStaticAssignments) + } + + printer.write("const exports = {") + try printer.indent { + printer.write(lines: data.exportsLines.map { "\($0)" }) + + let hierarchicalLines = try namespaceBuilder.buildHierarchicalExportsObject( + exportedSkeletons: exportedSkeletons, + intrinsicRegistry: intrinsicRegistry, + renderFunctionImpl: { function in + let (js, _) = try self.renderExportedFunction(function: function) + return js + } + ) + printer.write(lines: hierarchicalLines) + } + printer.write("};") + printer.write("_exports = exports;") + + let globalThisLines = namespaceBuilder.buildGlobalThisAssignments(exportedSkeletons: exportedSkeletons) + printer.write(lines: globalThisLines) + + printer.write("return exports;") + + return printer.lines + } + + private func generateImportedTypeDefinitions() -> [String] { + let printer = CodeFragmentPrinter() + + for unified in skeletons { + guard let skeletonSet = unified.imported else { continue } + for fileSkeleton in skeletonSet.children { + for type in fileSkeleton.types { + printer.write("export interface \(type.name) {") + printer.indent() + + // Add methods + for method in type.methods { + let methodName = method.jsName ?? method.name + let methodSignature = + "\(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 { + let propertyName = getter.jsName ?? getter.name + propertyNames.insert(propertyName) + let hasSetter = type.setters.contains { ($0.jsName ?? $0.name) == propertyName } + let propertySignature = + hasSetter + ? "\(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 { + let propertyName = setter.jsName ?? setter.name + guard !propertyNames.contains(propertyName) else { continue } + printer.write("\(renderTSPropertyName(propertyName)): \(resolveTypeScriptType(setter.type));") + } + + printer.unindent() + printer.write("}") + } + } + } + + return printer.lines + } + + class ExportedThunkBuilder { + var body: CodeFragmentPrinter + var cleanupCode: CodeFragmentPrinter + var parameterForwardings: [String] = [] + let effects: Effects + let scope: JSGlueVariableScope + let context: IntrinsicJSFragment.PrintCodeContext + + init(effects: Effects, hasDirectAccessToSwiftClass: Bool = true, intrinsicRegistry: JSIntrinsicRegistry) { + self.effects = effects + self.scope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) + self.body = CodeFragmentPrinter() + self.cleanupCode = CodeFragmentPrinter() + self.context = IntrinsicJSFragment.PrintCodeContext( + scope: scope, + printer: body, + cleanupCode: cleanupCode, + hasDirectAccessToSwiftClass: hasDirectAccessToSwiftClass + ) + } + + func lowerParameter(param: Parameter) throws { + let loweringFragment = try IntrinsicJSFragment.lowerParameter(type: param.type) + assert( + loweringFragment.parameters.count == 1, + "Lowering fragment should have exactly one parameter to lower" + ) + let loweredValues = try loweringFragment.printCode([param.name], context) + parameterForwardings.append(contentsOf: loweredValues) + } + + func lowerSelf() { + parameterForwardings.append("this.pointer") + } + + func call(abiName: String, returnType: BridgeType) throws -> String? { + if effects.isAsync { + return try _call(abiName: abiName, returnType: .jsObject(nil)) + } else { + return try _call(abiName: abiName, returnType: returnType) + } + } + + private func _call(abiName: String, returnType: BridgeType) throws -> String? { + let call = "instance.exports.\(abiName)(\(parameterForwardings.joined(separator: ", ")))" + let liftingFragment = try IntrinsicJSFragment.liftReturn(type: returnType) + assert( + liftingFragment.parameters.count <= 1, + "Lifting fragment should have at most one parameter to lift" + ) + let fragmentArguments: [String] + if liftingFragment.parameters.isEmpty { + body.write("\(call);") + fragmentArguments = [] + } else { + let returnVariable = scope.variable("ret") + body.write("const \(returnVariable) = \(call);") + fragmentArguments = [returnVariable] + } + let liftedValues = try liftingFragment.printCode(fragmentArguments, context) + assert(liftedValues.count <= 1, "Lifting fragment should produce at most one value") + return liftedValues.first + } + + func callConstructor(abiName: String) -> String { + let call = + "\(JSGlueVariableScope.reservedInstance).exports.\(abiName)(\(parameterForwardings.joined(separator: ", ")))" + body.write("const ret = \(call);") + return "ret" } func checkExceptionLines() -> [String] { guard effects.isThrows else { return [] } + let exceptionVariable = JSGlueVariableScope.reservedStorageToReturnException return [ - "if (tmpRetException) {", + "if (\(exceptionVariable)) {", // TODO: Implement "take" operation - " const error = swift.memory.getObject(tmpRetException);", - " swift.memory.release(tmpRetException);", - " tmpRetException = undefined;", + " const error = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(exceptionVariable));", + " \(JSGlueVariableScope.reservedSwift).memory.release(\(exceptionVariable));", + " \(exceptionVariable) = undefined;", " throw error;", "}", ] } + /// Renders the thunk body (body code, cleanup, exception handling, and optional return) into a printer. + func renderFunctionBody(into printer: CodeFragmentPrinter, returnExpr: String?) { + printer.write(contentsOf: body) + printer.write(contentsOf: cleanupCode) + printer.write(lines: checkExceptionLines()) + if let returnExpr = returnExpr { + printer.write("return \(returnExpr);") + } + } + func renderFunction( name: String, parameters: [Parameter], - returnType: BridgeType, returnExpr: String?, - isMethod: Bool + declarationPrefixKeyword: String? ) -> [String] { - var funcLines: [String] = [] - funcLines.append( - "\(isMethod ? "" : "function ")\(name)(\(parameters.map { $0.name }.joined(separator: ", "))) {" + let printer = CodeFragmentPrinter() + + let parameterList = DefaultValueUtils.formatParameterList(parameters) + + printer.write( + "\(declarationPrefixKeyword.map { "\($0) "} ?? "")\(name)(\(parameterList)) {" ) - funcLines.append(contentsOf: bodyLines.map { $0.indent(count: 4) }) - funcLines.append(contentsOf: cleanupLines.map { $0.indent(count: 4) }) - funcLines.append(contentsOf: checkExceptionLines().map { $0.indent(count: 4) }) - if let returnExpr = returnExpr { - funcLines.append("return \(returnExpr);".indent(count: 4)) + printer.indent { + renderFunctionBody(into: printer, returnExpr: returnExpr) + } + printer.write("}") + + return printer.lines + } + } + + /// Returns TypeScript type string for a BridgeType, using full paths for enums + /// If the type is an enum, looks up the ExportedEnum and uses its tsFullPath + /// Otherwise, uses the default tsType property + private func resolveTypeScriptType(_ type: BridgeType) -> String { + return Self.resolveTypeScriptType(type, exportedSkeletons: skeletons.compactMap(\.exported)) + } + + /// Static helper for resolving TypeScript types with full enum paths + /// Can be used by both BridgeJSLink and NamespaceBuilder + fileprivate static func resolveTypeScriptType(_ type: BridgeType, exportedSkeletons: [ExportedSkeleton]) -> String { + switch type { + case .caseEnum(let name), .rawValueEnum(let name, _), + .associatedValueEnum(let name), .namespaceEnum(let name): + // Look up the enum to get its tsFullPath + for skeleton in exportedSkeletons { + for enumDef in skeleton.enums { + if enumDef.name == name || enumDef.swiftCallName == name { + // Use the stored tsFullPath which has the full namespace + switch type { + case .namespaceEnum: + return enumDef.tsFullPath + default: + if enumDef.emitStyle == .tsEnum { + return enumDef.tsFullPath + } + return "\(enumDef.tsFullPath)Tag" + } + } + } + } + return type.tsType + case .swiftStruct(let name): + return name.components(separatedBy: ".").last ?? name + case .nullable(let wrapped, let kind): + let base = resolveTypeScriptType(wrapped, exportedSkeletons: exportedSkeletons) + return "\(base) | \(kind.absenceLiteral)" + 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)[]" + case .dictionary(let valueType): + let valueTypeStr = resolveTypeScriptType(valueType, exportedSkeletons: exportedSkeletons) + return "Record" + default: + return type.tsType + } + } + + private func renderTSSignature(parameters: [Parameter], returnType: BridgeType, effects: Effects) -> String { + let returnTypeWithEffect: String + if effects.isAsync { + returnTypeWithEffect = "Promise<\(resolveTypeScriptType(returnType))>" + } else { + returnTypeWithEffect = resolveTypeScriptType(returnType) + } + let parameterSignatures = parameters.map { param in + let optional = param.hasDefault ? "?" : "" + return "\(param.name)\(optional): \(resolveTypeScriptType(param.type))" + } + 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) + lines.append(contentsOf: jsDocLines) + } + + func renderExportedStruct( + _ structDefinition: ExportedStruct + ) throws -> (js: [String], dtsType: [String], dtsExportEntry: [String]) { + let structName = structDefinition.name + let hasConstructor = structDefinition.constructor != nil + let staticMethods = structDefinition.methods.filter { $0.effects.isStatic } + let staticProperties = structDefinition.properties.filter { $0.isStatic } + + let dtsTypePrinter = CodeFragmentPrinter() + dtsTypePrinter.write("export interface \(structName) {") + let instanceProps = structDefinition.properties.filter { !$0.isStatic } + dtsTypePrinter.indent { + for property in instanceProps { + let tsType = resolveTypeScriptType(property.type) + dtsTypePrinter.write("\(property.name): \(tsType);") + } + for method in structDefinition.methods where !method.effects.isStatic { + let jsDocLines = DefaultValueUtils.formatJSDoc(for: method.parameters) + dtsTypePrinter.write(lines: jsDocLines) + let signature = renderTSSignature( + parameters: method.parameters, + returnType: method.returnType, + effects: method.effects + ) + dtsTypePrinter.write("\(method.name)\(signature);") + } + } + dtsTypePrinter.write("}") + + guard hasConstructor || !staticMethods.isEmpty || !staticProperties.isEmpty else { + return (js: [], dtsType: dtsTypePrinter.lines, dtsExportEntry: []) + } + + let jsPrinter = CodeFragmentPrinter() + jsPrinter.write("\(structName): {") + try jsPrinter.indent { + // Constructor as 'init' function + if let constructor = structDefinition.constructor { + let thunkBuilder = ExportedThunkBuilder( + effects: constructor.effects, + intrinsicRegistry: intrinsicRegistry + ) + for param in constructor.parameters { + try thunkBuilder.lowerParameter(param: param) + } + let returnExpr = try thunkBuilder.call( + abiName: constructor.abiName, + returnType: .swiftStruct(structDefinition.swiftCallName) + ) + + let constructorPrinter = CodeFragmentPrinter() + let paramList = DefaultValueUtils.formatParameterList(constructor.parameters) + constructorPrinter.write("init: function(\(paramList)) {") + constructorPrinter.indent { + thunkBuilder.renderFunctionBody(into: constructorPrinter, returnExpr: returnExpr) + } + constructorPrinter.write("},") + jsPrinter.write(lines: constructorPrinter.lines) + } + + for property in staticProperties { + let propertyLines = try renderStaticPropertyForExportObject( + property: property, + className: structName + ) + jsPrinter.write(lines: propertyLines) + } + + for method in staticMethods { + let methodLines = try renderStaticMethodForExportObject(method: method) + jsPrinter.write(lines: methodLines) + } + } + jsPrinter.write("},") + + let dtsExportEntryPrinter = CodeFragmentPrinter() + dtsExportEntryPrinter.write("\(structName): {") + dtsExportEntryPrinter.indent { + if let constructor = structDefinition.constructor { + let jsDocLines = DefaultValueUtils.formatJSDoc(for: constructor.parameters) + dtsExportEntryPrinter.write(lines: jsDocLines) + dtsExportEntryPrinter.write( + "init\(renderTSSignature(parameters: constructor.parameters, returnType: .swiftStruct(structDefinition.swiftCallName), effects: constructor.effects));" + ) + } + for property in staticProperties { + let readonly = property.isReadonly ? "readonly " : "" + dtsExportEntryPrinter.write("\(readonly)\(property.name): \(resolveTypeScriptType(property.type));") + } + for method in staticMethods { + let jsDocLines = DefaultValueUtils.formatJSDoc(for: method.parameters) + dtsExportEntryPrinter.write(lines: jsDocLines) + dtsExportEntryPrinter.write( + "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));" + ) + } + } + dtsExportEntryPrinter.write("}") + + return (js: jsPrinter.lines, dtsType: dtsTypePrinter.lines, dtsExportEntry: dtsExportEntryPrinter.lines) + } + + func renderExportedEnum( + _ enumDefinition: ExportedEnum + ) throws -> (jsTopLevel: [String], jsExportEntry: [String], dtsType: [String], dtsExportEntry: [String]) { + var jsTopLevelLines: [String] = [] + var dtsTypeLines: [String] = [] + let scope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) + let printer = CodeFragmentPrinter() + let context = IntrinsicJSFragment.PrintCodeContext( + scope: scope, + printer: printer, + cleanupCode: CodeFragmentPrinter() + ) + let enumValuesName = enumDefinition.valuesName + + switch enumDefinition.enumType { + case .simple: + let fragment = IntrinsicJSFragment.simpleEnumHelper(enumDefinition: enumDefinition) + _ = try fragment.printCode([enumValuesName], context) + jsTopLevelLines.append(contentsOf: printer.lines) + case .rawValue: + guard enumDefinition.rawType != nil else { + throw BridgeJSLinkError(message: "Raw value enum \(enumDefinition.name) is missing rawType") + } + + let fragment = IntrinsicJSFragment.rawValueEnumHelper(enumDefinition: enumDefinition) + _ = try fragment.printCode([enumValuesName], context) + jsTopLevelLines.append(contentsOf: printer.lines) + case .associatedValue: + let fragment = IntrinsicJSFragment.associatedValueEnumValues(enumDefinition: enumDefinition) + _ = try fragment.printCode([enumValuesName], context) + jsTopLevelLines.append(contentsOf: printer.lines) + case .namespace: + break + } + + if enumDefinition.namespace == nil { + dtsTypeLines.append(contentsOf: generateDeclarations(enumDefinition: enumDefinition)) + } + + var jsExportEntryLines: [String] = [] + var dtsExportEntryLines: [String] = [] + + if enumDefinition.enumType != .namespace + && enumDefinition.emitStyle != .tsEnum + && enumDefinition.namespace == nil + { + var enumMethodLines: [String] = [] + for function in enumDefinition.staticMethods { + let methodLines = try renderStaticMethodForExportObject(method: function) + enumMethodLines.append(contentsOf: methodLines) + } + + var enumPropertyLines: [String] = [] + for property in enumDefinition.staticProperties { + let propertyLines = try renderStaticPropertyForExportObject( + property: property, + className: nil + ) + enumPropertyLines.append(contentsOf: propertyLines) + } + + let exportsPrinter = CodeFragmentPrinter() + + if !enumMethodLines.isEmpty || !enumPropertyLines.isEmpty { + exportsPrinter.write("\(enumDefinition.name): {") + exportsPrinter.indent { + exportsPrinter.write("...\(enumValuesName),") + var allLines = enumMethodLines + enumPropertyLines + if let lastLineIndex = allLines.indices.last, allLines[lastLineIndex].hasSuffix(",") { + allLines[lastLineIndex] = String(allLines[lastLineIndex].dropLast()) + } + exportsPrinter.write(lines: allLines) + } + exportsPrinter.write("},") + } else { + exportsPrinter.write("\(enumDefinition.name): \(enumValuesName),") + } + + jsExportEntryLines = exportsPrinter.lines + dtsExportEntryLines = ["\(enumDefinition.name): \(enumDefinition.objectTypeName)"] + } + + return (jsTopLevelLines, jsExportEntryLines, dtsTypeLines, dtsExportEntryLines) + } + + private func generateDeclarations(enumDefinition: ExportedEnum) -> [String] { + let printer = CodeFragmentPrinter() + let enumValuesName = enumDefinition.valuesName + + switch enumDefinition.emitStyle { + case .tsEnum: + switch enumDefinition.enumType { + case .simple, .rawValue: + printer.write("export enum \(enumDefinition.name) {") + printer.indent { + for (index, enumCase) in enumDefinition.cases.enumerated() { + let caseName = enumCase.name.capitalizedFirstLetter + let value = enumCase.jsValue( + rawType: enumDefinition.rawType, + index: index + ) + printer.write("\(caseName) = \(value),") + } + } + printer.write("}") + printer.nextLine() + case .associatedValue, .namespace: + break + } + + case .const: + printer.write("export const \(enumValuesName): {") + switch enumDefinition.enumType { + case .simple, .rawValue: + printer.indent { + for (index, enumCase) in enumDefinition.cases.enumerated() { + let caseName = enumCase.name.capitalizedFirstLetter + let value = enumCase.jsValue( + rawType: enumDefinition.rawType, + index: index + ) + printer.write("readonly \(caseName): \(value);") + } + + } + printer.write("};") + printer.write( + "export type \(enumDefinition.name)Tag = typeof \(enumValuesName)[keyof typeof \(enumValuesName)];" + ) + printer.nextLine() + case .associatedValue: + printer.indent { + printer.write("readonly Tag: {") + printer.indent { + for (index, enumCase) in enumDefinition.cases.enumerated() { + let caseName = enumCase.name.capitalizedFirstLetter + printer.write("readonly \(caseName): \(index);") + } + } + printer.write("};") + + } + printer.write("};") + printer.nextLine() + + var unionParts: [String] = [] + for enumCase in enumDefinition.cases { + if enumCase.associatedValues.isEmpty { + unionParts.append( + "{ tag: typeof \(enumValuesName).Tag.\(enumCase.name.capitalizedFirstLetter) }" + ) + } else { + var fields: [String] = [ + "tag: typeof \(enumValuesName).Tag.\(enumCase.name.capitalizedFirstLetter)" + ] + for (associatedValueIndex, associatedValue) in enumCase.associatedValues.enumerated() { + let prop = associatedValue.label ?? "param\(associatedValueIndex)" + fields.append("\(prop): \(resolveTypeScriptType(associatedValue.type))") + } + unionParts.append("{ \(fields.joined(separator: "; ")) }") + } + } + + let unionTypeName = + enumDefinition.emitStyle == .tsEnum ? enumDefinition.name : "\(enumDefinition.name)Tag" + printer.write("export type \(unionTypeName) =") + printer.write(" " + unionParts.joined(separator: " | ")) + printer.nextLine() + case .namespace: + break + } + } + return printer.lines + } + +} + +extension BridgeJSLink { + + func renderExportedFunction( + function: ExportedFunction + ) throws -> (js: [String], dts: [String]) { + if function.effects.isStatic, let staticContext = function.staticContext { + return try renderStaticFunction(function: function, staticContext: staticContext) + } + + let thunkBuilder = ExportedThunkBuilder( + effects: function.effects, + intrinsicRegistry: intrinsicRegistry + ) + for param in function.parameters { + try thunkBuilder.lowerParameter(param: param) + } + let returnExpr = try thunkBuilder.call(abiName: function.abiName, returnType: function.returnType) + let funcLines = thunkBuilder.renderFunction( + name: function.abiName, + parameters: function.parameters, + returnExpr: returnExpr, + declarationPrefixKeyword: "function" + ) + var dtsLines: [String] = [] + + appendJSDocIfNeeded(for: function.parameters, to: &dtsLines) + + dtsLines.append( + "\(function.name)\(renderTSSignature(parameters: function.parameters, returnType: function.returnType, effects: function.effects));" + ) + + return (funcLines, dtsLines) + } + + private func renderStaticFunction( + function: ExportedFunction, + staticContext: StaticContext + ) throws -> (js: [String], dts: [String]) { + switch staticContext { + case .className(let name), .structName(let name): + return try renderStaticFunction(function: function, className: name) + case .enumName(let enumName): + return try renderEnumStaticFunction(function: function, enumName: enumName) + case .namespaceEnum: + if let namespace = function.namespace, !namespace.isEmpty { + return try renderNamespaceFunction( + function: function, + namespace: namespace.joined(separator: ".") + ) + } else { + return try renderExportedFunction(function: function) + } + } + } + + private func renderStaticFunction( + function: ExportedFunction, + className: String + ) throws -> (js: [String], dts: [String]) { + let thunkBuilder = ExportedThunkBuilder( + effects: function.effects, + intrinsicRegistry: intrinsicRegistry + ) + for param in function.parameters { + try thunkBuilder.lowerParameter(param: param) + } + let returnExpr = try thunkBuilder.call(abiName: function.abiName, returnType: function.returnType) + + let funcLines = thunkBuilder.renderFunction( + name: function.name, + parameters: function.parameters, + returnExpr: returnExpr, + declarationPrefixKeyword: "static" + ) + + var dtsLines: [String] = [] + + appendJSDocIfNeeded(for: function.parameters, to: &dtsLines) + + dtsLines.append( + "static \(function.name)\(renderTSSignature(parameters: function.parameters, returnType: function.returnType, effects: function.effects));" + ) + + return (funcLines, dtsLines) + } + + private func renderEnumStaticFunction( + function: ExportedFunction, + enumName: String + ) throws -> (js: [String], dts: [String]) { + let thunkBuilder = ExportedThunkBuilder( + effects: function.effects, + intrinsicRegistry: intrinsicRegistry + ) + for param in function.parameters { + try thunkBuilder.lowerParameter(param: param) + } + let returnExpr = try thunkBuilder.call(abiName: function.abiName, returnType: function.returnType) + + let printer = CodeFragmentPrinter() + printer.write("\(function.name)(\(function.parameters.map { $0.name }.joined(separator: ", "))) {") + printer.indent { + thunkBuilder.renderFunctionBody(into: printer, returnExpr: returnExpr) + } + printer.write("},") + + var dtsLines: [String] = [] + + appendJSDocIfNeeded(for: function.parameters, to: &dtsLines) + + dtsLines.append( + "\(function.name)\(renderTSSignature(parameters: function.parameters, returnType: function.returnType, effects: function.effects));" + ) + + return (printer.lines, dtsLines) + } + + private func renderNamespaceFunction( + function: ExportedFunction, + namespace: String + ) throws -> (js: [String], dts: [String]) { + let thunkBuilder = ExportedThunkBuilder( + effects: function.effects, + intrinsicRegistry: intrinsicRegistry + ) + for param in function.parameters { + try thunkBuilder.lowerParameter(param: param) + } + let returnExpr = try thunkBuilder.call(abiName: function.abiName, returnType: function.returnType) + + let funcLines = thunkBuilder.renderFunction( + name: function.abiName, + parameters: function.parameters, + returnExpr: returnExpr, + declarationPrefixKeyword: "function" + ) + + let dtsLines: [String] = [] + + return (funcLines, dtsLines) + } + + /// Renders a static method for use in an export object + private func renderStaticMethodForExportObject( + method: ExportedFunction + ) throws -> [String] { + let thunkBuilder = ExportedThunkBuilder( + effects: method.effects, + intrinsicRegistry: intrinsicRegistry + ) + for param in method.parameters { + try thunkBuilder.lowerParameter(param: param) + } + let returnExpr = try thunkBuilder.call(abiName: method.abiName, returnType: method.returnType) + + let methodPrinter = CodeFragmentPrinter() + methodPrinter.write( + "\(method.name): function(\(method.parameters.map { $0.name }.joined(separator: ", "))) {" + ) + methodPrinter.indent { + thunkBuilder.renderFunctionBody(into: methodPrinter, returnExpr: returnExpr) + } + methodPrinter.write("},") + return methodPrinter.lines + } + + /// Renders a static property getter/setter for use in an export object + private func renderStaticPropertyForExportObject( + property: ExportedProperty, + className: String? + ) throws -> [String] { + let propertyPrinter = CodeFragmentPrinter() + + // Generate getter + let getterThunkBuilder = ExportedThunkBuilder( + effects: Effects(isAsync: false, isThrows: false), + intrinsicRegistry: intrinsicRegistry + ) + let getterReturnExpr = try getterThunkBuilder.call( + abiName: className != nil + ? property.getterAbiName(className: className!) + : property.getterAbiName(), + returnType: property.type + ) + + propertyPrinter.write("get \(property.name)() {") + propertyPrinter.indent { + getterThunkBuilder.renderFunctionBody(into: propertyPrinter, returnExpr: getterReturnExpr) + } + propertyPrinter.write("},") + + // Generate setter if not readonly + if !property.isReadonly { + let setterThunkBuilder = ExportedThunkBuilder( + effects: Effects(isAsync: false, isThrows: false), + intrinsicRegistry: intrinsicRegistry + ) + try setterThunkBuilder.lowerParameter( + param: Parameter(label: "value", name: "value", type: property.type) + ) + _ = try setterThunkBuilder.call( + abiName: className != nil + ? property.setterAbiName(className: className!) + : property.setterAbiName(), + returnType: .void + ) + + propertyPrinter.write("set \(property.name)(value) {") + propertyPrinter.indent { + setterThunkBuilder.renderFunctionBody(into: propertyPrinter, returnExpr: nil) + } + propertyPrinter.write("},") + } + + return propertyPrinter.lines + } + + func renderExportedClass( + _ klass: ExportedClass + ) throws -> (js: [String], dtsType: [String], dtsExportEntry: [String]) { + let jsPrinter = CodeFragmentPrinter() + let dtsTypePrinter = CodeFragmentPrinter() + let dtsExportEntryPrinter = CodeFragmentPrinter() + + dtsTypePrinter.write("export interface \(klass.name) extends SwiftHeapObject {") + dtsExportEntryPrinter.write("\(klass.name): {") + jsPrinter.write("class \(klass.name) extends SwiftHeapObject {") + + // Always add __construct and constructor methods for all classes + jsPrinter.indent { + jsPrinter.write("static __construct(ptr) {") + jsPrinter.indent { + jsPrinter.write( + "return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_\(klass.name)_deinit, \(klass.name).prototype);" + ) + } + jsPrinter.write("}") + jsPrinter.nextLine() + } + + if let constructor: ExportedConstructor = klass.constructor { + let thunkBuilder = ExportedThunkBuilder( + effects: constructor.effects, + intrinsicRegistry: intrinsicRegistry + ) + for param in constructor.parameters { + try thunkBuilder.lowerParameter(param: param) + } + + let constructorParamList = DefaultValueUtils.formatParameterList(constructor.parameters) + + jsPrinter.indent { + jsPrinter.write("constructor(\(constructorParamList)) {") + let returnExpr = thunkBuilder.callConstructor(abiName: constructor.abiName) + jsPrinter.indent { + thunkBuilder.renderFunctionBody( + into: jsPrinter, + returnExpr: "\(klass.name).__construct(\(returnExpr))" + ) + } + jsPrinter.write("}") + } + + dtsExportEntryPrinter.indent { + let jsDocLines = DefaultValueUtils.formatJSDoc(for: constructor.parameters) + for line in jsDocLines { + dtsExportEntryPrinter.write(line) + } + dtsExportEntryPrinter.write( + "new\(renderTSSignature(parameters: constructor.parameters, returnType: .swiftHeapObject(klass.name), effects: constructor.effects));" + ) + } + } + + for method in klass.methods { + if method.effects.isStatic { + let thunkBuilder = ExportedThunkBuilder( + effects: method.effects, + intrinsicRegistry: intrinsicRegistry + ) + for param in method.parameters { + try thunkBuilder.lowerParameter(param: param) + } + let returnExpr = try thunkBuilder.call(abiName: method.abiName, returnType: method.returnType) + + jsPrinter.indent { + jsPrinter.write( + lines: thunkBuilder.renderFunction( + name: method.name, + parameters: method.parameters, + returnExpr: returnExpr, + declarationPrefixKeyword: "static" + ) + ) + } + + dtsExportEntryPrinter.indent { + dtsExportEntryPrinter.write( + "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));" + ) + } + } else { + let thunkBuilder = ExportedThunkBuilder( + effects: method.effects, + intrinsicRegistry: intrinsicRegistry + ) + thunkBuilder.lowerSelf() + for param in method.parameters { + try thunkBuilder.lowerParameter(param: param) + } + let returnExpr = try thunkBuilder.call(abiName: method.abiName, returnType: method.returnType) + + jsPrinter.indent { + jsPrinter.write( + lines: thunkBuilder.renderFunction( + name: method.name, + parameters: method.parameters, + returnExpr: returnExpr, + declarationPrefixKeyword: nil + ) + ) + } + + dtsTypePrinter.indent { + dtsTypePrinter.write( + "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));" + ) + } + } + } + + // Generate property getters and setters + for property in klass.properties { + try renderClassProperty( + property: property, + className: klass.name, + isStatic: property.isStatic, + jsPrinter: jsPrinter, + dtsPrinter: property.isStatic ? dtsExportEntryPrinter : dtsTypePrinter + ) + } + + jsPrinter.write("}") + dtsTypePrinter.write("}") + dtsExportEntryPrinter.write("}") + + return (jsPrinter.lines, dtsTypePrinter.lines, dtsExportEntryPrinter.lines) + } + + private func renderClassProperty( + property: ExportedProperty, + className: String, + isStatic: Bool, + jsPrinter: CodeFragmentPrinter, + dtsPrinter: CodeFragmentPrinter + ) throws { + let getterThunkBuilder = ExportedThunkBuilder( + effects: Effects(isAsync: false, isThrows: false), + intrinsicRegistry: intrinsicRegistry + ) + if !isStatic { + getterThunkBuilder.lowerSelf() + } + + let getterAbiName = isStatic ? property.getterAbiName() : property.getterAbiName(className: className) + let getterReturnExpr = try getterThunkBuilder.call(abiName: getterAbiName, returnType: property.type) + + let getterKeyword = isStatic ? "static get" : "get" + jsPrinter.indent { + jsPrinter.write( + lines: getterThunkBuilder.renderFunction( + name: property.name, + parameters: [], + returnExpr: getterReturnExpr, + declarationPrefixKeyword: getterKeyword + ) + ) + } + + // Generate setter if not readonly + if !property.isReadonly { + let setterThunkBuilder = ExportedThunkBuilder( + effects: Effects(isAsync: false, isThrows: false), + intrinsicRegistry: intrinsicRegistry + ) + if !isStatic { + setterThunkBuilder.lowerSelf() + } + try setterThunkBuilder.lowerParameter( + param: Parameter(label: "value", name: "value", type: property.type) + ) + + let setterAbiName = isStatic ? property.setterAbiName() : property.setterAbiName(className: className) + _ = try setterThunkBuilder.call(abiName: setterAbiName, returnType: .void) + + let setterKeyword = isStatic ? "static set" : "set" + jsPrinter.indent { + jsPrinter.write( + lines: setterThunkBuilder.renderFunction( + name: property.name, + parameters: [.init(label: nil, name: "value", type: property.type)], + returnExpr: nil, + declarationPrefixKeyword: setterKeyword + ) + ) + } + } + + // Add instance property to TypeScript interface definition + let readonly = property.isReadonly ? "readonly " : "" + dtsPrinter.indent { + dtsPrinter.write("\(readonly)\(property.name): \(property.type.tsType);") + } + } + + class ImportedThunkBuilder { + let body: CodeFragmentPrinter + let scope: JSGlueVariableScope + let cleanupCode: CodeFragmentPrinter + let context: BridgeContext + var parameterNames: [String] = [] + var parameterForwardings: [String] = [] + let printContext: IntrinsicJSFragment.PrintCodeContext + + init(context: BridgeContext = .importTS, intrinsicRegistry: JSIntrinsicRegistry) { + self.body = CodeFragmentPrinter() + self.scope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) + self.cleanupCode = CodeFragmentPrinter() + self.context = context + self.printContext = IntrinsicJSFragment.PrintCodeContext( + scope: scope, + printer: body, + cleanupCode: cleanupCode + ) + } + + func liftSelf() { + parameterNames.append("self") + } + + func liftParameter(param: Parameter) throws { + let liftingFragment = try IntrinsicJSFragment.liftParameter(type: param.type, context: context) + let valuesToLift: [String] + if liftingFragment.parameters.count == 0 { + valuesToLift = [] + } else if liftingFragment.parameters.count == 1 { + parameterNames.append(param.name) + valuesToLift = [scope.variable(param.name)] + } else { + valuesToLift = liftingFragment.parameters.map { scope.variable(param.name + $0.capitalizedFirstLetter) } + parameterNames.append(contentsOf: valuesToLift) + } + let liftedValues = try liftingFragment.printCode(valuesToLift, printContext) + assert(liftedValues.count == 1, "Lifting fragment should produce exactly one value") + parameterForwardings.append(contentsOf: liftedValues) + } + + func renderFunction( + name: String?, + returnExpr: String?, + returnType: BridgeType + ) -> [String] { + let printer = CodeFragmentPrinter() + + printer.write("function\(name.map { " \($0)" } ?? "")(\(parameterNames.joined(separator: ", "))) {") + printer.indent { + printer.write("try {") + printer.indent { + printer.write(contentsOf: body) + if let returnExpr = returnExpr { + printer.write("return \(returnExpr);") + } + } + printer.write("} catch (error) {") + printer.indent { + printer.write("setException(error);") + if let abiReturnType = returnType.abiReturnType { + printer.write("return \(abiReturnType.placeholderValue)") + } + } + printer.write("}") + } + printer.write("}") + + 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 call(name: name, fromObjectExpr: "imports", returnType: returnType) + } + + func call(calleeExpr: String, returnType: BridgeType) throws -> String? { + let callExpr = "\(calleeExpr)(\(parameterForwardings.joined(separator: ", ")))" + return try self.call(callExpr: callExpr, returnType: returnType) + } + + private func call(callExpr: String, returnType: BridgeType) throws -> String? { + let loweringFragment = try IntrinsicJSFragment.lowerReturn(type: returnType, context: context) + let returnExpr: String? + if loweringFragment.parameters.count == 0 { + body.write("\(callExpr);") + returnExpr = nil + } else { + let resultVariable = scope.variable("ret") + body.write("let \(resultVariable) = \(callExpr);") + returnExpr = resultVariable + } + return try lowerReturnValue( + returnType: returnType, + returnExpr: returnExpr, + loweringFragment: loweringFragment + ) + } + + 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: calleeExpr, + returnType: returnType + ) + } + + func callStaticMethod(on objectExpr: String, name: String, returnType: BridgeType) throws -> String? { + let calleeExpr = Self.propertyAccessExpr(objectExpr: objectExpr, propertyName: name) + return try call( + 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 .nullable(let wrappedType, _) = returnType else { + fatalError("usesSideChannelForOptionalReturn returned true for non-optional type") + } + + let resultVar = scope.variable("ret") + body.write( + "let \(resultVar) = \(accessExpr);" + ) + + let fragment = try IntrinsicJSFragment.protocolPropertyOptionalToSideChannel(wrappedType: wrappedType) + _ = try fragment.printCode([resultVar], printContext) + + return nil // Side-channel types return nil (no direct return value) + } + + return try call( + callExpr: accessExpr, + returnType: returnType + ) + } + + func callPropertySetter(name: String, returnType: BridgeType) { + 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, 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 = Self.propertyAccessExpr(objectExpr: fromObjectExpr, propertyName: name) + + let returnExpr: String? + if loweringFragment.parameters.count == 0 { + body.write("\(expr);") + returnExpr = nil + } else { + let resultVariable = scope.variable("ret") + body.write("let \(resultVariable) = \(expr);") + returnExpr = resultVariable + } + + return try lowerReturnValue( + returnType: returnType, + returnExpr: returnExpr, + loweringFragment: loweringFragment + ) + } + + func getImportProperty(name: String, returnType: BridgeType) throws -> String? { + return try getImportProperty(name: name, fromObjectExpr: "imports", returnType: returnType) + } + + private func lowerReturnValue( + returnType: BridgeType, + returnExpr: String?, + loweringFragment: IntrinsicJSFragment + ) throws -> String? { + assert(loweringFragment.parameters.count <= 1, "Lowering fragment should have at most one parameter") + let loweredValues = try loweringFragment.printCode( + returnExpr.map { [$0] } ?? [], + printContext + ) + assert(loweredValues.count <= 1, "Lowering fragment should produce at most one value") + return loweredValues.first + } + + 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 { + var moduleName: String + private let importedPrinter: CodeFragmentPrinter = CodeFragmentPrinter() + private let dtsImportPrinter: CodeFragmentPrinter = CodeFragmentPrinter() + var importedLines: [String] { + importedPrinter.lines + } + + var dtsImportLines: [String] { + dtsImportPrinter.lines + } + + init(moduleName: String) { + self.moduleName = moduleName + importedPrinter.write( + "const \(moduleName) = importObject[\"\(moduleName)\"] = importObject[\"\(moduleName)\"] || {};" + ) + } + + func assignToImportObject(name: String, function: [String]) { + var js = function + js[0] = "\(moduleName)[\"\(name)\"] = " + js[0] + importedPrinter.write(lines: js) + } + + func appendDts(_ lines: [String]) { + dtsImportPrinter.write(lines: lines) + } + } + + struct NamespaceBuilder { + func collectAllNamespacePaths(exportedSkeletons: [ExportedSkeleton]) -> Set<[String]> { + return Set( + exportedSkeletons.flatMap { skeleton in + let itemNamespaces = + (skeleton.functions.compactMap(\.namespace) + skeleton.classes.compactMap(\.namespace) + + skeleton.enums.filter { $0.namespace != nil && $0.enumType != .namespace } + .compactMap(\.namespace)) + + let namespaceEnumPaths = skeleton.enums + .filter { $0.enumType == .namespace } + .filter { !$0.staticProperties.isEmpty || !$0.staticMethods.isEmpty } + .map { ($0.namespace ?? []) + [$0.name] } + + return itemNamespaces + namespaceEnumPaths + } + ) + } + + func buildNamespaceInitialization(exportedSkeletons: [ExportedSkeleton]) -> [String] { + let globalSkeletons = exportedSkeletons.filter { $0.exposeToGlobal } + guard !globalSkeletons.isEmpty else { return [] } + let allNamespacePaths = collectAllNamespacePaths(exportedSkeletons: globalSkeletons) + return generateNamespaceInitializationCode(namespacePaths: allNamespacePaths) + } + + func buildTopLevelNamespaceInitialization( + exportedSkeletons: [ExportedSkeleton] + ) -> [String] { + let globalSkeletons = exportedSkeletons.filter { $0.exposeToGlobal } + guard !globalSkeletons.isEmpty else { return [] } + + var namespacedEnumPaths: Set<[String]> = [] + for skeleton in globalSkeletons { + for enumDef in skeleton.enums where enumDef.namespace != nil && enumDef.enumType != .namespace { + namespacedEnumPaths.insert(enumDef.namespace!) + } + } + + let initCode = generateNamespaceInitializationCode(namespacePaths: namespacedEnumPaths) + + let printer = CodeFragmentPrinter() + printer.write(lines: initCode) + + for skeleton in globalSkeletons { + for enumDef in skeleton.enums where enumDef.namespace != nil && enumDef.enumType != .namespace { + let namespacePath = enumDef.namespace!.joined(separator: ".") + printer.write("globalThis.\(namespacePath).\(enumDef.valuesName) = \(enumDef.valuesName);") + } + } + + return printer.lines + } + + func buildGlobalThisAssignments(exportedSkeletons: [ExportedSkeleton]) -> [String] { + let printer = CodeFragmentPrinter() + + for skeleton in exportedSkeletons where skeleton.exposeToGlobal { + for klass in skeleton.classes where klass.namespace != nil { + let namespacePath = klass.namespace!.joined(separator: ".") + printer.write("globalThis.\(namespacePath).\(klass.name) = exports.\(namespacePath).\(klass.name);") + } + for function in skeleton.functions where function.namespace != nil { + let namespacePath = function.namespace!.joined(separator: ".") + printer.write( + "globalThis.\(namespacePath).\(function.name) = exports.\(namespacePath).\(function.name);" + ) + } + for enumDef in skeleton.enums where enumDef.enumType == .namespace { + for function in enumDef.staticMethods { + let fullNamespace = (enumDef.namespace ?? []) + [enumDef.name] + let namespacePath = fullNamespace.joined(separator: ".") + printer.write( + "globalThis.\(namespacePath).\(function.name) = exports.\(namespacePath).\(function.name);" + ) + } + for property in enumDef.staticProperties { + let fullNamespace = (enumDef.namespace ?? []) + [enumDef.name] + let namespacePath = fullNamespace.joined(separator: ".") + let exportsPath = "exports.\(namespacePath)" + + printer.write("Object.defineProperty(globalThis.\(namespacePath), '\(property.name)', {") + printer.indent { + printer.write("get: () => \(exportsPath).\(property.name),") + if !property.isReadonly { + printer.write("set: (value) => { \(exportsPath).\(property.name) = value; }") + } + } + printer.write("});") + } + } + } + + return printer.lines + } + + private func generateNamespaceInitializationCode(namespacePaths: Set<[String]>) -> [String] { + let printer = CodeFragmentPrinter() + var allUniqueNamespaces: [String] = [] + var seen = Set() + + namespacePaths.forEach { namespacePath in + namespacePath.enumerated().forEach { (index, _) in + let path = namespacePath[0...index].joined(separator: ".") + if seen.insert(path).inserted { + allUniqueNamespaces.append(path) + } + } + } + + allUniqueNamespaces.sorted().forEach { namespace in + printer.write("if (typeof globalThis.\(namespace) === 'undefined') {") + printer.indent { + printer.write("globalThis.\(namespace) = {};") + } + printer.write("}") + } + + return printer.lines + } + + private struct NamespaceContent { + var functions: [ExportedFunction] = [] + var classes: [ExportedClass] = [] + var enums: [ExportedEnum] = [] + var staticProperties: [ExportedProperty] = [] + var functionJsLines: [(name: String, lines: [String])] = [] + var functionDtsLines: [(name: String, lines: [String])] = [] + var classDtsLines: [(name: String, lines: [String])] = [] + var enumDtsLines: [(name: String, line: String)] = [] + var propertyJsLines: [String] = [] + } + + private final class NamespaceNode { + let name: String + var children: [String: NamespaceNode] = [:] + var content: NamespaceContent = NamespaceContent() + + init(name: String) { + self.name = name + } + + func addChild(_ childName: String) -> NamespaceNode { + if let existing = children[childName] { + return existing + } + let newChild = NamespaceNode(name: childName) + children[childName] = newChild + return newChild + } + } + + private func buildExportsTree( + rootNode: NamespaceNode, + exportedSkeletons: [ExportedSkeleton] + ) { + for skeleton in exportedSkeletons { + for function in skeleton.functions where function.namespace != nil { + var currentNode = rootNode + for part in function.namespace! { + currentNode = currentNode.addChild(part) + } + currentNode.content.functions.append(function) + } + + for klass in skeleton.classes where klass.namespace != nil { + var currentNode = rootNode + for part in klass.namespace! { + currentNode = currentNode.addChild(part) + } + currentNode.content.classes.append(klass) + } + + for enumDef in skeleton.enums where enumDef.namespace != nil && enumDef.enumType != .namespace { + var currentNode = rootNode + for part in enumDef.namespace! { + currentNode = currentNode.addChild(part) + } + currentNode.content.enums.append(enumDef) + } + + for enumDef in skeleton.enums where enumDef.enumType == .namespace { + for property in enumDef.staticProperties { + let fullNamespace = (enumDef.namespace ?? []) + [enumDef.name] + var currentNode = rootNode + for part in fullNamespace { + currentNode = currentNode.addChild(part) + } + currentNode.content.staticProperties.append(property) + } + for function in enumDef.staticMethods { + let fullNamespace = (enumDef.namespace ?? []) + [enumDef.name] + var currentNode = rootNode + for part in fullNamespace { + currentNode = currentNode.addChild(part) + } + currentNode.content.functions.append(function) + } + } } - funcLines.append("}") - return funcLines } - } - private func renderTSSignature(parameters: [Parameter], returnType: BridgeType, effects: Effects) -> String { - let returnTypeWithEffect: String - if effects.isAsync { - returnTypeWithEffect = "Promise<\(returnType.tsType)>" - } else { - returnTypeWithEffect = returnType.tsType - } - return - "(\(parameters.map { "\($0.name): \($0.type.tsType)" }.joined(separator: ", "))): \(returnTypeWithEffect)" - } + fileprivate func buildHierarchicalExportsType( + exportedSkeletons: [ExportedSkeleton], + renderClassEntry: (ExportedClass) -> [String], + renderFunctionSignature: (ExportedFunction) -> String + ) -> [String] { + let printer = CodeFragmentPrinter() + let rootNode = NamespaceNode(name: "") - func renderExportedFunction(function: ExportedFunction) -> (js: [String], dts: [String]) { - let thunkBuilder = ExportedThunkBuilder(effects: function.effects) - for param in function.parameters { - thunkBuilder.lowerParameter(param: param) - } - let returnExpr = thunkBuilder.call(abiName: function.abiName, returnType: function.returnType) - let funcLines = thunkBuilder.renderFunction( - name: function.abiName, - parameters: function.parameters, - returnType: function.returnType, - returnExpr: returnExpr, - isMethod: false - ) - var dtsLines: [String] = [] - dtsLines.append( - "\(function.name)\(renderTSSignature(parameters: function.parameters, returnType: function.returnType, effects: function.effects));" - ) + buildExportsTree(rootNode: rootNode, exportedSkeletons: exportedSkeletons) - return (funcLines, dtsLines) - } + for (_, node) in rootNode.children { + populateTypeScriptExportLines( + node: node, + renderClassEntry: renderClassEntry, + renderFunctionSignature: renderFunctionSignature + ) + } - func renderExportedClass(_ klass: ExportedClass) -> (js: [String], dtsType: [String], dtsExportEntry: [String]) { - var jsLines: [String] = [] - var dtsTypeLines: [String] = [] - var dtsExportEntryLines: [String] = [] + printExportsTypeHierarchy(node: rootNode, printer: printer) - dtsTypeLines.append("export interface \(klass.name) extends SwiftHeapObject {") - dtsExportEntryLines.append("\(klass.name): {") - jsLines.append("class \(klass.name) extends SwiftHeapObject {") + return printer.lines + } - // Always add __construct and constructor methods for all classes - var constructorLines: [String] = [] - constructorLines.append("static __construct(ptr) {") - constructorLines.append( - "return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_\(klass.name)_deinit, \(klass.name).prototype);" - .indent(count: 4) - ) - constructorLines.append("}") - constructorLines.append("") - jsLines.append(contentsOf: constructorLines.map { $0.indent(count: 4) }) + private func populateTypeScriptExportLines( + node: NamespaceNode, + renderClassEntry: (ExportedClass) -> [String], + renderFunctionSignature: (ExportedFunction) -> String + ) { + for function in node.content.functions { + let signature = renderFunctionSignature(function) + node.content.functionDtsLines.append((function.name, [signature])) + } - if let constructor: ExportedConstructor = klass.constructor { - let thunkBuilder = ExportedThunkBuilder(effects: constructor.effects) - for param in constructor.parameters { - thunkBuilder.lowerParameter(param: param) + for klass in node.content.classes { + let entry = renderClassEntry(klass) + node.content.classDtsLines.append((klass.name, entry)) } - var funcLines: [String] = [] - funcLines.append("") - funcLines.append("constructor(\(constructor.parameters.map { $0.name }.joined(separator: ", "))) {") - let returnExpr = thunkBuilder.callConstructor(abiName: constructor.abiName) - funcLines.append(contentsOf: thunkBuilder.bodyLines.map { $0.indent(count: 4) }) - funcLines.append(contentsOf: thunkBuilder.cleanupLines.map { $0.indent(count: 4) }) - funcLines.append(contentsOf: thunkBuilder.checkExceptionLines().map { $0.indent(count: 4) }) - funcLines.append("return \(klass.name).__construct(\(returnExpr));".indent(count: 4)) - funcLines.append("}") - jsLines.append(contentsOf: funcLines.map { $0.indent(count: 4) }) - dtsExportEntryLines.append( - "new\(renderTSSignature(parameters: constructor.parameters, returnType: .swiftHeapObject(klass.name), effects: constructor.effects));" - .indent(count: 4) - ) + for enumDef in node.content.enums { + node.content.enumDtsLines.append((enumDef.name, "\(enumDef.name): \(enumDef.objectTypeName)")) + } + + for (_, childNode) in node.children { + populateTypeScriptExportLines( + node: childNode, + renderClassEntry: renderClassEntry, + renderFunctionSignature: renderFunctionSignature + ) + } } - for method in klass.methods { - let thunkBuilder = ExportedThunkBuilder(effects: method.effects) - thunkBuilder.lowerSelf() - for param in method.parameters { - thunkBuilder.lowerParameter(param: param) - } - let returnExpr = thunkBuilder.call(abiName: method.abiName, returnType: method.returnType) - jsLines.append( - contentsOf: thunkBuilder.renderFunction( - name: method.name, - parameters: method.parameters, - returnType: method.returnType, - returnExpr: returnExpr, - isMethod: true - ).map { $0.indent(count: 4) } - ) - dtsTypeLines.append( - "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));" - .indent(count: 4) + fileprivate func buildHierarchicalExportsObject( + exportedSkeletons: [ExportedSkeleton], + intrinsicRegistry: JSIntrinsicRegistry, + renderFunctionImpl: (ExportedFunction) throws -> [String] + ) throws -> [String] { + let printer = CodeFragmentPrinter() + let rootNode = NamespaceNode(name: "") + + buildExportsTree(rootNode: rootNode, exportedSkeletons: exportedSkeletons) + + try populateJavaScriptExportLines(node: rootNode, renderFunctionImpl: renderFunctionImpl) + + try populatePropertyImplementations( + node: rootNode, + intrinsicRegistry: intrinsicRegistry ) - } - jsLines.append("}") - dtsTypeLines.append("}") - dtsExportEntryLines.append("}") + printExportsObjectHierarchy(node: rootNode, printer: printer, currentPath: []) - return (jsLines, dtsTypeLines, dtsExportEntryLines) - } + return printer.lines + } - func renderGlobalNamespace(namespacedFunctions: [ExportedFunction], namespacedClasses: [ExportedClass]) -> [String] - { - var lines: [String] = [] - var uniqueNamespaces: [String] = [] - var seen = Set() + private func populateJavaScriptExportLines( + node: NamespaceNode, + renderFunctionImpl: (ExportedFunction) throws -> [String] + ) throws { + for function in node.content.functions { + let impl = try renderFunctionImpl(function) + node.content.functionJsLines.append((function.name, impl)) + } - let functionNamespacePaths: Set<[String]> = Set( - namespacedFunctions - .compactMap { $0.namespace } - ) - let classNamespacePaths: Set<[String]> = Set( - namespacedClasses - .compactMap { $0.namespace } - ) + for (_, childNode) in node.children { + try populateJavaScriptExportLines(node: childNode, renderFunctionImpl: renderFunctionImpl) + } + } + + private func populatePropertyImplementations( + node: NamespaceNode, + intrinsicRegistry: JSIntrinsicRegistry + ) throws { + for property in node.content.staticProperties { + // Generate getter + let getterThunkBuilder = ExportedThunkBuilder( + effects: Effects(isAsync: false, isThrows: false), + intrinsicRegistry: intrinsicRegistry + ) + let getterReturnExpr = try getterThunkBuilder.call( + abiName: property.getterAbiName(), + returnType: property.type + ) - let allNamespacePaths = - functionNamespacePaths - .union(classNamespacePaths) + let getterPrinter = CodeFragmentPrinter() + getterPrinter.write("get \(property.name)() {") + getterPrinter.indent { + getterPrinter.write(contentsOf: getterThunkBuilder.body) + getterPrinter.write(contentsOf: getterThunkBuilder.cleanupCode) + getterPrinter.write(lines: getterThunkBuilder.checkExceptionLines()) + if let returnExpr = getterReturnExpr { + getterPrinter.write("return \(returnExpr);") + } + } + getterPrinter.write("},") + + var propertyLines = getterPrinter.lines + + // Generate setter if not readonly + if !property.isReadonly { + let setterThunkBuilder = ExportedThunkBuilder( + effects: Effects(isAsync: false, isThrows: false), + intrinsicRegistry: intrinsicRegistry + ) + try setterThunkBuilder.lowerParameter( + param: Parameter(label: "value", name: "value", type: property.type) + ) + _ = try setterThunkBuilder.call( + abiName: property.setterAbiName(), + returnType: BridgeType.void + ) + + let setterPrinter = CodeFragmentPrinter() + setterPrinter.write("set \(property.name)(value) {") + setterPrinter.indent { + setterPrinter.write(contentsOf: setterThunkBuilder.body) + setterPrinter.write(contentsOf: setterThunkBuilder.cleanupCode) + setterPrinter.write(lines: setterThunkBuilder.checkExceptionLines()) + } + setterPrinter.write("},") - allNamespacePaths.forEach { namespacePath in - namespacePath.makeIterator().enumerated().forEach { (index, _) in - let path = namespacePath[0...index].joined(separator: ".") - if seen.insert(path).inserted { - uniqueNamespaces.append(path) + propertyLines.append(contentsOf: setterPrinter.lines) } + + node.content.propertyJsLines.append(contentsOf: propertyLines) } - } - uniqueNamespaces.sorted().forEach { namespace in - lines.append("if (typeof globalThis.\(namespace) === 'undefined') {") - lines.append(" globalThis.\(namespace) = {};") - lines.append("}") + // Recursively process child nodes + for (_, childNode) in node.children { + try populatePropertyImplementations( + node: childNode, + intrinsicRegistry: intrinsicRegistry + ) + } } - namespacedClasses.forEach { klass in - let namespacePath: String = klass.namespace?.joined(separator: ".") ?? "" - lines.append("globalThis.\(namespacePath).\(klass.name) = exports.\(klass.name);") - } + private func printExportsTypeHierarchy(node: NamespaceNode, printer: CodeFragmentPrinter) { + for (childName, childNode) in node.children.sorted(by: { $0.key < $1.key }) { + printer.write("\(childName): {") + printer.indent { + for (_, lines) in childNode.content.classDtsLines.sorted(by: { $0.name < $1.name }) { + printer.write(lines: lines) + } - namespacedFunctions.forEach { function in - let namespacePath: String = function.namespace?.joined(separator: ".") ?? "" - lines.append("globalThis.\(namespacePath).\(function.name) = exports.\(function.name);") - } + for (_, line) in childNode.content.enumDtsLines.sorted(by: { $0.name < $1.name }) { + printer.write(line) + } - return lines - } + for property in childNode.content.staticProperties.sorted(by: { $0.name < $1.name }) { + let readonly = property.isReadonly ? "readonly " : "" + printer.write("\(readonly)\(property.name): \(property.type.tsType);") + } - class ImportedThunkBuilder { - var bodyLines: [String] = [] - var parameterNames: [String] = [] - var parameterForwardings: [String] = [] + for (_, lines) in childNode.content.functionDtsLines.sorted(by: { $0.name < $1.name }) { + for line in lines { + printer.write(line) + } + } - func liftSelf() { - parameterNames.append("self") + printExportsTypeHierarchy(node: childNode, printer: printer) + } + printer.write("},") + } } - func liftParameter(param: Parameter) { - parameterNames.append(param.name) - switch param.type { - case .string: - let stringObjectName = "\(param.name)Object" - // TODO: Implement "take" operation - bodyLines.append("const \(stringObjectName) = swift.memory.getObject(\(param.name));") - bodyLines.append("swift.memory.release(\(param.name));") - parameterForwardings.append(stringObjectName) - case .jsObject: - parameterForwardings.append("swift.memory.getObject(\(param.name))") - default: - parameterForwardings.append(param.name) + private func printExportsObjectHierarchy( + node: NamespaceNode, + printer: CodeFragmentPrinter, + currentPath: [String] = [] + ) { + for (childName, childNode) in node.children.sorted(by: { $0.key < $1.key }) { + let newPath = currentPath + [childName] + printer.write("\(childName): {") + printer.indent { + for klass in childNode.content.classes.sorted(by: { $0.name < $1.name }) { + printer.write("\(klass.name),") + } + + for enumDef in childNode.content.enums.sorted(by: { $0.name < $1.name }) { + printer.write("\(enumDef.name): \(enumDef.valuesName),") + } + + // Print function and property implementations + printer.write(lines: childNode.content.propertyJsLines) + for (name, lines) in childNode.content.functionJsLines.sorted(by: { $0.name < $1.name }) { + var modifiedLines = lines + if !modifiedLines.isEmpty { + modifiedLines[0] = "\(name): " + modifiedLines[0] + modifiedLines[modifiedLines.count - 1] += "," + } + printer.write(lines: modifiedLines) + } + + printExportsObjectHierarchy(node: childNode, printer: printer, currentPath: newPath) + } + printer.write("},") } } - func renderFunction( - name: String, - returnExpr: String?, - returnType: BridgeType + /// Generates TypeScript declarations for all namespaces + /// + /// This function enables properly grouping all Swift code within given namespaces + /// regardless of location in Swift input files. It uses a tree-based structure to + /// properly create unique namespace declarations that avoid namespace duplication in TS and generate + /// predictable declarations in sorted order. + /// + /// The function collects all namespaced items (functions, classes, enums) from the + /// exported skeletons and builds a hierarchical namespace tree. It then traverses + /// this tree to generate TypeScript namespace declarations that mirror the Swift + /// namespace structure. + /// - Parameters: + /// - exportedSkeletons: Exported Swift structures to generate namespaces for + /// - renderTSSignatureCallback: closure to generate TS signature that aligns with rest of codebase + /// - Returns: Array of TypeScript declaration lines defining the global namespace structure + func namespaceDeclarations( + exportedSkeletons: [ExportedSkeleton], + renderTSSignatureCallback: @escaping ([Parameter], BridgeType, Effects) -> String ) -> [String] { - var funcLines: [String] = [] - funcLines.append( - "function \(name)(\(parameterNames.joined(separator: ", "))) {" - ) - funcLines.append("try {".indent(count: 4)) - funcLines.append(contentsOf: bodyLines.map { $0.indent(count: 8) }) - if let returnExpr = returnExpr { - funcLines.append("return \(returnExpr);".indent(count: 8)) - } - funcLines.append("} catch (error) {".indent(count: 4)) - funcLines.append("setException(error);".indent(count: 8)) - if let abiReturnType = returnType.abiReturnType { - funcLines.append("return \(abiReturnType.placeholderValue)".indent(count: 8)) + let printer = CodeFragmentPrinter() + + let globalSkeletons = exportedSkeletons.filter { $0.exposeToGlobal } + let nonGlobalSkeletons = exportedSkeletons.filter { !$0.exposeToGlobal } + + if !globalSkeletons.isEmpty { + let globalRootNode = NamespaceNode(name: "") + buildExportsTree(rootNode: globalRootNode, exportedSkeletons: globalSkeletons) + + if !globalRootNode.children.isEmpty { + printer.write("export {};") + printer.nextLine() + printer.write("declare global {") + printer.indent() + generateNamespaceDeclarationsForNode( + node: globalRootNode, + depth: 1, + printer: printer, + exposeToGlobal: true, + exportedSkeletons: exportedSkeletons, + renderTSSignatureCallback: renderTSSignatureCallback + ) + printer.unindent() + printer.write("}") + printer.nextLine() + } } - funcLines.append("}".indent(count: 4)) - funcLines.append("}") - return funcLines - } - func call(name: String, returnType: BridgeType) { - let call = "imports.\(name)(\(parameterForwardings.joined(separator: ", ")))" - if returnType == .void { - bodyLines.append("\(call);") - } else { - bodyLines.append("let ret = \(call);") + if !nonGlobalSkeletons.isEmpty { + let localRootNode = NamespaceNode(name: "") + buildExportsTree(rootNode: localRootNode, exportedSkeletons: nonGlobalSkeletons) + + if !localRootNode.children.isEmpty { + generateNamespaceDeclarationsForNode( + node: localRootNode, + depth: 1, + printer: printer, + exposeToGlobal: false, + exportedSkeletons: exportedSkeletons, + renderTSSignatureCallback: renderTSSignatureCallback + ) + } } - } - func callConstructor(name: String) { - let call = "new imports.\(name)(\(parameterForwardings.joined(separator: ", ")))" - bodyLines.append("let ret = \(call);") + return printer.lines } - func callMethod(name: String, returnType: BridgeType) { - let call = "swift.memory.getObject(self).\(name)(\(parameterForwardings.joined(separator: ", ")))" - if returnType == .void { - bodyLines.append("\(call);") - } else { - bodyLines.append("let ret = \(call);") - } - } + private func generateNamespaceDeclarationsForNode( + node: NamespaceNode, + depth: Int, + printer: CodeFragmentPrinter, + exposeToGlobal: Bool, + exportedSkeletons: [ExportedSkeleton], + renderTSSignatureCallback: @escaping ([Parameter], BridgeType, Effects) -> String + ) { + func hasContent(node: NamespaceNode) -> Bool { + // Enums are always included + if !node.content.enums.isEmpty { + return true + } - func callPropertyGetter(name: String, returnType: BridgeType) { - let call = "swift.memory.getObject(self).\(name)" - bodyLines.append("let ret = \(call);") - } + // When exposeToGlobal is true, classes, functions, and properties are included + if exposeToGlobal { + if !node.content.classes.isEmpty || !node.content.functions.isEmpty + || !node.content.staticProperties.isEmpty + { + return true + } + } - func callPropertySetter(name: String, returnType: BridgeType) { - let call = "swift.memory.getObject(self).\(name) = \(parameterForwardings.joined(separator: ", "))" - bodyLines.append("\(call);") - } + // Check if any child has content + for (_, childNode) in node.children { + if hasContent(node: childNode) { + return true + } + } - func lowerReturnValue(returnType: BridgeType) throws -> String? { - switch returnType { - case .void: - return nil - case .string: - bodyLines.append("tmpRetBytes = textEncoder.encode(ret);") - return "tmpRetBytes.length" - case .int, .float, .double: - return "ret" - case .bool: - return "ret !== 0" - case .jsObject: - return "swift.memory.retain(ret)" - case .swiftHeapObject: - throw BridgeJSLinkError(message: "Swift heap object is not supported in imported functions") + return false } - } - } - class ImportObjectBuilder { - var moduleName: String - var importedLines: [String] = [] - var dtsImportLines: [String] = [] + func generateNamespaceDeclarations(node: NamespaceNode, depth: Int) { + let sortedChildren = node.children.sorted { $0.key < $1.key } - init(moduleName: String) { - self.moduleName = moduleName - importedLines.append( - "const \(moduleName) = importObject[\"\(moduleName)\"] = importObject[\"\(moduleName)\"] || {};" - ) - } + for (childName, childNode) in sortedChildren { + // Skip empty namespaces + guard hasContent(node: childNode) else { + continue + } - func assignToImportObject(name: String, function: [String]) { - var js = function - js[0] = "\(moduleName)[\"\(name)\"] = " + js[0] - importedLines.append(contentsOf: js) - } + let exportKeyword = exposeToGlobal ? "" : "export " + printer.write("\(exportKeyword)namespace \(childName) {") + printer.indent() + + // Only include classes when exposeToGlobal is true + if exposeToGlobal { + let sortedClasses = childNode.content.classes.sorted { $0.name < $1.name } + for klass in sortedClasses { + printer.write("class \(klass.name) {") + printer.indent { + if let constructor = klass.constructor { + let constructorSignature = + "constructor(\(constructor.parameters.map { "\($0.name): \($0.type.tsType)" }.joined(separator: ", ")));" + printer.write(constructorSignature) + } + + let sortedMethods = klass.methods.sorted { $0.name < $1.name } + for method in sortedMethods { + let methodSignature = + "\(method.name)\(renderTSSignatureCallback(method.parameters, method.returnType, method.effects));" + printer.write(methodSignature) + } + } + printer.write("}") + } + } - func appendDts(_ lines: [String]) { - dtsImportLines.append(contentsOf: lines) + // Generate enum definitions within declare global namespace + let sortedEnums = childNode.content.enums.sorted { $0.name < $1.name } + for enumDefinition in sortedEnums { + let style: EnumEmitStyle = enumDefinition.emitStyle + let enumValuesName = enumDefinition.valuesName + switch enumDefinition.enumType { + case .simple: + switch style { + case .tsEnum: + printer.write("enum \(enumDefinition.name) {") + printer.indent { + for (index, enumCase) in enumDefinition.cases.enumerated() { + let caseName = enumCase.name.capitalizedFirstLetter + printer.write("\(caseName) = \(index),") + } + } + printer.write("}") + case .const: + printer.write("const \(enumValuesName): {") + printer.indent { + for (index, enumCase) in enumDefinition.cases.enumerated() { + let caseName = enumCase.name.capitalizedFirstLetter + printer.write("readonly \(caseName): \(index);") + } + } + printer.write("};") + printer.write( + "type \(enumDefinition.name)Tag = typeof \(enumValuesName)[keyof typeof \(enumValuesName)];" + ) + } + case .rawValue: + guard let rawType = enumDefinition.rawType else { continue } + switch style { + case .tsEnum: + printer.write("enum \(enumDefinition.name) {") + printer.indent { + for (index, enumCase) in enumDefinition.cases.enumerated() { + let caseName = enumCase.name.capitalizedFirstLetter + let value = enumCase.jsValue( + rawType: rawType, + index: index + ) + printer.write("\(caseName) = \(value),") + } + } + printer.write("}") + case .const: + printer.write("const \(enumValuesName): {") + printer.indent { + for (index, enumCase) in enumDefinition.cases.enumerated() { + let caseName = enumCase.name.capitalizedFirstLetter + let value = enumCase.jsValue( + rawType: rawType, + index: index + ) + printer.write("readonly \(caseName): \(value);") + } + } + printer.write("};") + printer.write( + "type \(enumDefinition.name)Tag = typeof \(enumValuesName)[keyof typeof \(enumValuesName)];" + ) + } + case .associatedValue: + printer.write("const \(enumValuesName): {") + printer.indent { + printer.write("readonly Tag: {") + printer.indent { + for (caseIndex, enumCase) in enumDefinition.cases.enumerated() { + let caseName = enumCase.name.capitalizedFirstLetter + printer.write("readonly \(caseName): \(caseIndex);") + } + } + printer.write("};") + } + printer.write("};") + + var unionParts: [String] = [] + for enumCase in enumDefinition.cases { + if enumCase.associatedValues.isEmpty { + unionParts.append( + "{ tag: typeof \(enumValuesName).Tag.\(enumCase.name.capitalizedFirstLetter) }" + ) + } else { + var fields: [String] = [ + "tag: typeof \(enumValuesName).Tag.\(enumCase.name.capitalizedFirstLetter)" + ] + for (associatedValueIndex, associatedValue) in enumCase.associatedValues + .enumerated() + { + let prop = associatedValue.label ?? "param\(associatedValueIndex)" + fields.append( + "\(prop): \(BridgeJSLink.resolveTypeScriptType(associatedValue.type, exportedSkeletons: exportedSkeletons))" + ) + } + unionParts.append("{ \(fields.joined(separator: "; ")) }") + } + } + let unionTypeName = + enumDefinition.emitStyle == .tsEnum ? enumDefinition.name : "\(enumDefinition.name)Tag" + printer.write("type \(unionTypeName) =") + printer.write(" " + unionParts.joined(separator: " | ")) + case .namespace: + continue + } + } + + // Only include functions and properties when exposeToGlobal is true + if exposeToGlobal { + let sortedFunctions = childNode.content.functions.sorted { $0.name < $1.name } + for function in sortedFunctions { + let signature = + "function \(function.name)\(renderTSSignatureCallback(function.parameters, function.returnType, function.effects));" + printer.write(signature) + } + let sortedProperties = childNode.content.staticProperties.sorted { $0.name < $1.name } + for property in sortedProperties { + let readonly = property.isReadonly ? "var " : "let " + printer.write("\(readonly)\(property.name): \(property.type.tsType);") + } + } + + generateNamespaceDeclarationsForNode( + node: childNode, + depth: depth + 1, + printer: printer, + exposeToGlobal: exposeToGlobal, + exportedSkeletons: exportedSkeletons, + renderTSSignatureCallback: renderTSSignatureCallback + ) + + printer.unindent() + printer.write("}") + } + } + + generateNamespaceDeclarations(node: node, depth: depth) } } @@ -808,26 +3070,57 @@ struct BridgeJSLink { importObjectBuilder: ImportObjectBuilder, function: ImportedFunctionSkeleton ) throws { - let thunkBuilder = ImportedThunkBuilder() + let thunkBuilder = ImportedThunkBuilder(intrinsicRegistry: intrinsicRegistry) for param in function.parameters { - thunkBuilder.liftParameter(param: param) + try thunkBuilder.liftParameter(param: param) } - thunkBuilder.call(name: function.name, returnType: function.returnType) - let returnExpr = try thunkBuilder.lowerReturnValue(returnType: function.returnType) + let 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) } + func renderImportedGlobalGetter( + importObjectBuilder: ImportObjectBuilder, + getter: ImportedGetterSkeleton + ) throws { + let thunkBuilder = ImportedThunkBuilder(intrinsicRegistry: intrinsicRegistry) + 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 + ) + if getter.from == nil { + importObjectBuilder.appendDts(["readonly \(renderTSPropertyName(jsName)): \(getter.type.tsType);"]) + } + importObjectBuilder.assignToImportObject(name: abiName, function: funcLines) + } + func renderImportedType( importObjectBuilder: ImportObjectBuilder, type: ImportedTypeSkeleton @@ -839,35 +3132,63 @@ struct BridgeJSLink { constructor: constructor ) } - for property in type.properties { - let getterAbiName = property.getterAbiName(context: type) - let (js, dts) = try renderImportedProperty( - property: property, + for getter in type.getters { + let getterAbiName = getter.abiName(context: type) + let (js, dts) = try renderImportedGetter( + getter: getter, abiName: getterAbiName, emitCall: { thunkBuilder in - thunkBuilder.callPropertyGetter(name: property.name, returnType: property.type) - return try thunkBuilder.lowerReturnValue(returnType: property.type) + return try thunkBuilder.callPropertyGetter( + name: getter.jsName ?? getter.name, + returnType: getter.type + ) } ) importObjectBuilder.assignToImportObject(name: getterAbiName, function: js) importObjectBuilder.appendDts(dts) + } - if !property.isReadonly { - let setterAbiName = property.setterAbiName(context: type) - let (js, dts) = try renderImportedProperty( - property: property, - abiName: setterAbiName, - emitCall: { thunkBuilder in - thunkBuilder.liftParameter( - param: Parameter(label: nil, name: "newValue", type: property.type) - ) - thunkBuilder.callPropertySetter(name: property.name, returnType: property.type) - return nil - } - ) - importObjectBuilder.assignToImportObject(name: setterAbiName, function: js) - importObjectBuilder.appendDts(dts) + for setter in type.setters { + let setterAbiName = setter.abiName(context: type) + let (js, dts) = try renderImportedSetter( + setter: setter, + abiName: setterAbiName, + emitCall: { thunkBuilder in + try thunkBuilder.liftParameter( + param: Parameter(label: nil, name: "newValue", type: setter.type) + ) + thunkBuilder.callPropertySetter(name: setter.jsName ?? setter.name, returnType: setter.type) + return nil + } + ) + importObjectBuilder.assignToImportObject(name: setterAbiName, function: js) + importObjectBuilder.appendDts(dts) + } + for method in type.staticMethods { + let abiName = method.abiName(context: type, operation: "static") + let (js, dts) = try renderImportedStaticMethod(context: type, method: method) + importObjectBuilder.assignToImportObject(name: abiName, function: js) + importObjectBuilder.appendDts(dts) + } + if type.from == nil, type.constructor != nil || !type.staticMethods.isEmpty { + let dtsPrinter = CodeFragmentPrinter() + dtsPrinter.write("\(type.name): {") + dtsPrinter.indent { + if let constructor = type.constructor { + let returnType = BridgeType.jsObject(type.name) + dtsPrinter.write( + "new\(renderTSSignature(parameters: constructor.parameters, returnType: returnType, effects: Effects(isAsync: false, isThrows: false)));" + ) + } + for method in type.staticMethods { + let methodName = method.jsName ?? method.name + let signature = + "\(renderTSPropertyName(methodName))\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: Effects(isAsync: false, isThrows: false)));" + dtsPrinter.write(signature) + } } + dtsPrinter.write("}") + importObjectBuilder.appendDts(dtsPrinter.lines) } for method in type.methods { let (js, dts) = try renderImportedMethod(context: type, method: method) @@ -881,13 +3202,17 @@ struct BridgeJSLink { type: ImportedTypeSkeleton, constructor: ImportedConstructorSkeleton ) throws { - let thunkBuilder = ImportedThunkBuilder() + let thunkBuilder = ImportedThunkBuilder(intrinsicRegistry: intrinsicRegistry) for param in constructor.parameters { - thunkBuilder.liftParameter(param: param) + try thunkBuilder.liftParameter(param: param) } let returnType = BridgeType.jsObject(type.name) - thunkBuilder.callConstructor(name: type.name) - let returnExpr = try thunkBuilder.lowerReturnValue(returnType: returnType) + let 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, @@ -895,26 +3220,62 @@ struct BridgeJSLink { returnType: returnType ) importObjectBuilder.assignToImportObject(name: abiName, function: funcLines) - importObjectBuilder.appendDts([ - "\(type.name): {", - "new\(renderTSSignature(parameters: constructor.parameters, returnType: returnType, effects: Effects(isAsync: false, isThrows: false)));" - .indent(count: 4), - "}", - ]) } - func renderImportedProperty( - property: ImportedPropertySkeleton, + func renderImportedGetter( + getter: ImportedGetterSkeleton, abiName: String, emitCall: (ImportedThunkBuilder) throws -> String? ) throws -> (js: [String], dts: [String]) { - let thunkBuilder = ImportedThunkBuilder() + let thunkBuilder = ImportedThunkBuilder(intrinsicRegistry: intrinsicRegistry) thunkBuilder.liftSelf() let returnExpr = try emitCall(thunkBuilder) let funcLines = thunkBuilder.renderFunction( name: abiName, returnExpr: returnExpr, - returnType: property.type + returnType: getter.type + ) + return (funcLines, []) + } + + func renderImportedSetter( + setter: ImportedSetterSkeleton, + abiName: String, + emitCall: (ImportedThunkBuilder) throws -> String? + ) throws -> (js: [String], dts: [String]) { + let thunkBuilder = ImportedThunkBuilder(intrinsicRegistry: intrinsicRegistry) + thunkBuilder.liftSelf() + let returnExpr = try emitCall(thunkBuilder) + let funcLines = thunkBuilder.renderFunction( + name: abiName, + returnExpr: returnExpr, + returnType: .void + ) + return (funcLines, []) + } + + func renderImportedStaticMethod( + context: ImportedTypeSkeleton, + method: ImportedFunctionSkeleton + ) throws -> (js: [String], dts: [String]) { + let thunkBuilder = ImportedThunkBuilder(intrinsicRegistry: intrinsicRegistry) + for param in method.parameters { + try thunkBuilder.liftParameter(param: param) + } + let importRootExpr = context.from == .global ? "globalThis" : "imports" + let constructorExpr = ImportedThunkBuilder.propertyAccessExpr( + objectExpr: importRootExpr, + propertyName: context.jsName ?? context.name + ) + let returnExpr = try thunkBuilder.callStaticMethod( + on: constructorExpr, + name: method.jsName ?? method.name, + returnType: method.returnType + ) + let funcLines = thunkBuilder.renderFunction( + name: method.abiName(context: context, operation: "static"), + returnExpr: returnExpr, + returnType: method.returnType ) return (funcLines, []) } @@ -923,13 +3284,12 @@ struct BridgeJSLink { context: ImportedTypeSkeleton, method: ImportedFunctionSkeleton ) throws -> (js: [String], dts: [String]) { - let thunkBuilder = ImportedThunkBuilder() + let thunkBuilder = ImportedThunkBuilder(intrinsicRegistry: intrinsicRegistry) thunkBuilder.liftSelf() for param in method.parameters { - thunkBuilder.liftParameter(param: param) + try thunkBuilder.liftParameter(param: param) } - thunkBuilder.callMethod(name: method.name, returnType: method.returnType) - let returnExpr = try thunkBuilder.lowerReturnValue(returnType: method.returnType) + let returnExpr = try thunkBuilder.callMethod(name: method.jsName ?? method.name, returnType: method.returnType) let funcLines = thunkBuilder.renderFunction( name: method.abiName(context: context), returnExpr: returnExpr, @@ -937,18 +3297,173 @@ struct BridgeJSLink { ) return (funcLines, []) } -} -struct BridgeJSLinkError: Error { - let message: String + func renderProtocolProperty( + importObjectBuilder: ImportObjectBuilder, + protocol: ExportedProtocol, + property: ExportedProtocolProperty + ) throws { + let getterAbiName = ABINameGenerator.generateABIName( + baseName: property.name, + namespace: nil, + staticContext: nil, + operation: "get", + className: `protocol`.name + ) + + let getterThunkBuilder = ImportedThunkBuilder( + context: .exportSwift, + intrinsicRegistry: intrinsicRegistry + ) + getterThunkBuilder.liftSelf() + let returnExpr = try getterThunkBuilder.callPropertyGetter(name: property.name, returnType: property.type) + let getterLines = getterThunkBuilder.renderFunction( + name: getterAbiName, + returnExpr: returnExpr, + returnType: property.type + ) + importObjectBuilder.assignToImportObject(name: getterAbiName, function: getterLines) + + if !property.isReadonly { + let setterAbiName = ABINameGenerator.generateABIName( + baseName: property.name, + namespace: nil, + staticContext: nil, + operation: "set", + className: `protocol`.name + ) + let setterThunkBuilder = ImportedThunkBuilder( + context: .exportSwift, + intrinsicRegistry: intrinsicRegistry + ) + setterThunkBuilder.liftSelf() + try setterThunkBuilder.liftParameter( + param: Parameter(label: nil, name: "value", type: property.type) + ) + setterThunkBuilder.callPropertySetter(name: property.name, returnType: property.type) + let setterLines = setterThunkBuilder.renderFunction( + name: setterAbiName, + returnExpr: nil, + returnType: .void + ) + importObjectBuilder.assignToImportObject(name: setterAbiName, function: setterLines) + } + } + + func renderProtocolMethod( + importObjectBuilder: ImportObjectBuilder, + protocol: ExportedProtocol, + method: ExportedFunction + ) throws { + let thunkBuilder = ImportedThunkBuilder( + context: .exportSwift, + intrinsicRegistry: intrinsicRegistry + ) + thunkBuilder.liftSelf() + for param in method.parameters { + try thunkBuilder.liftParameter(param: param) + } + let returnExpr = try thunkBuilder.callMethod(name: method.name, returnType: method.returnType) + let funcLines = thunkBuilder.renderFunction( + name: method.abiName, + returnExpr: returnExpr, + returnType: method.returnType + ) + importObjectBuilder.assignToImportObject(name: method.abiName, function: funcLines) + } } -extension String { - func indent(count: Int) -> String { - return String(repeating: " ", count: count) + self +/// Utility enum for generating default value representations in JavaScript/TypeScript +enum DefaultValueUtils { + enum OutputFormat { + case javascript + case typescript + } + + /// Generates default value representation for JavaScript or TypeScript + static func format(_ defaultValue: DefaultValue, as format: OutputFormat) -> String { + switch defaultValue { + case .string(let value): + let escapedValue = + format == .javascript + ? escapeForJavaScript(value) + : value // TypeScript doesn't need escape in doc comments + return "\"\(escapedValue)\"" + case .int(let value): + return "\(value)" + case .float(let value): + return "\(value)" + case .double(let value): + return "\(value)" + case .bool(let value): + return value ? "true" : "false" + case .null: + return "null" + case .enumCase(let enumName, let caseName): + let simpleName = enumName.components(separatedBy: ".").last ?? enumName + let jsEnumName = format == .javascript ? "\(simpleName)\(ExportedEnum.valuesSuffix)" : simpleName + return "\(jsEnumName).\(caseName.capitalizedFirstLetter)" + case .object(let className): + return "new \(className)()" + case .objectWithArguments(let className, let args): + let argStrings = args.map { arg in + Self.format(arg, as: format) + } + return "new \(className)(\(argStrings.joined(separator: ", ")))" + case .structLiteral(_, let fields): + let fieldStrings = fields.map { field in + "\(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: ", "))]" + } + } + + private static func escapeForJavaScript(_ string: String) -> String { + return + string + .replacingOccurrences(of: "\\", with: "\\\\") + .replacingOccurrences(of: "\"", with: "\\\"") + } + + /// Generates JSDoc comment lines for parameters with default values + static func formatJSDoc(for parameters: [Parameter]) -> [String] { + let paramsWithDefaults = parameters.filter { $0.hasDefault } + guard !paramsWithDefaults.isEmpty else { + return [] + } + + var jsDocLines: [String] = ["/**"] + for param in paramsWithDefaults { + if let defaultValue = param.defaultValue { + let defaultDoc = format(defaultValue, as: .typescript) + jsDocLines.append(" * @param \(param.name) - Optional parameter (default: \(defaultDoc))") + } + } + jsDocLines.append(" */") + return jsDocLines + } + + /// Generates a JavaScript parameter list with default values + static func formatParameterList(_ parameters: [Parameter]) -> String { + return parameters.map { param in + if let defaultValue = param.defaultValue { + let defaultJs = format(defaultValue, as: .javascript) + return "\(param.name) = \(defaultJs)" + } + return param.name + }.joined(separator: ", ") } } +struct BridgeJSLinkError: Error { + let message: String +} + extension BridgeType { var tsType: String { switch self { @@ -956,7 +3471,7 @@ extension BridgeType { return "void" case .string: return "string" - case .int: + case .int, .uint: return "number" case .float: return "number" @@ -966,8 +3481,39 @@ extension BridgeType { return "boolean" case .jsObject(let name): return name ?? "any" + case .jsValue: + return "any" case .swiftHeapObject(let name): return name + case .unsafePointer: + return "number" + case .nullable(let wrappedType, let kind): + return "\(wrappedType.tsType) | \(kind.absenceLiteral)" + case .caseEnum(let name): + return "\(name)Tag" + case .rawValueEnum(let name, _): + return "\(name)Tag" + case .associatedValueEnum(let name): + return "\(name)Tag" + case .swiftStruct(let name): + return "\(name)Tag" + case .namespaceEnum(let name): + return name + case .swiftProtocol(let name): + return name + case .closure(let signature, _): + let paramTypes = signature.parameters.enumerated().map { index, param in + "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)[]" + case .dictionary(let valueType): + return "Record" } } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift new file mode 100644 index 000000000..da21a6e08 --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -0,0 +1,3461 @@ +#if canImport(BridgeJSSkeleton) +import BridgeJSSkeleton +#endif +#if canImport(BridgeJSUtilities) +import BridgeJSUtilities +#endif + +/// A scope for variables for JS glue code +final class JSGlueVariableScope { + // MARK: - Reserved variables + + static let reservedSwift = "swift" + static let reservedInstance = "instance" + static let reservedMemory = "memory" + static let reservedSetException = "setException" + static let reservedStorageToReturnString = "tmpRetString" + static let reservedStorageToReturnBytes = "tmpRetBytes" + static let reservedStorageToReturnException = "tmpRetException" + static let reservedStorageToReturnOptionalBool = "tmpRetOptionalBool" + static let reservedStorageToReturnOptionalInt = "tmpRetOptionalInt" + static let reservedStorageToReturnOptionalFloat = "tmpRetOptionalFloat" + static let reservedStorageToReturnOptionalDouble = "tmpRetOptionalDouble" + static let reservedStorageToReturnOptionalHeapObject = "tmpRetOptionalHeapObject" + static let reservedTextEncoder = "textEncoder" + static let reservedTextDecoder = "textDecoder" + static let reservedStringStack = "strStack" + static let reservedI32Stack = "i32Stack" + static let reservedF32Stack = "f32Stack" + static let reservedF64Stack = "f64Stack" + static let reservedPointerStack = "ptrStack" + static let reservedTmpStructCleanups = "tmpStructCleanups" + static let reservedEnumHelpers = "enumHelpers" + static let reservedStructHelpers = "structHelpers" + static let reservedSwiftClosureRegistry = "swiftClosureRegistry" + static let reservedMakeSwiftClosure = "makeClosure" + + private let intrinsicRegistry: JSIntrinsicRegistry + + private var variables: Set = [ + reservedSwift, + reservedInstance, + reservedMemory, + reservedSetException, + reservedStorageToReturnString, + reservedStorageToReturnBytes, + reservedStorageToReturnException, + reservedStorageToReturnOptionalBool, + reservedStorageToReturnOptionalInt, + reservedStorageToReturnOptionalFloat, + reservedStorageToReturnOptionalDouble, + reservedStorageToReturnOptionalHeapObject, + reservedTextEncoder, + reservedTextDecoder, + reservedStringStack, + reservedI32Stack, + reservedF32Stack, + reservedF64Stack, + reservedPointerStack, + reservedTmpStructCleanups, + reservedEnumHelpers, + reservedStructHelpers, + reservedSwiftClosureRegistry, + reservedMakeSwiftClosure, + ] + + init(intrinsicRegistry: JSIntrinsicRegistry) { + self.intrinsicRegistry = intrinsicRegistry + } + + /// Returns a unique variable name in the scope based on the given name hint. + /// + /// - Parameter hint: A hint for the variable name. + /// - Returns: A unique variable name. + func variable(_ hint: String) -> String { + if variables.insert(hint).inserted { + return hint + } + var suffixedName: String + var suffix = 1 + repeat { + suffixedName = hint + suffix.description + suffix += 1 + } while !variables.insert(suffixedName).inserted + return suffixedName + } + + func registerIntrinsic(_ name: String, build: (CodeFragmentPrinter) throws -> Void) rethrows { + try intrinsicRegistry.register(name: name, build: build) + } + + func makeChildScope() -> JSGlueVariableScope { + JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) + } +} + +extension JSGlueVariableScope { + // MARK: Parameter + + func emitPushI32Parameter(_ value: String, printer: CodeFragmentPrinter) { + printer.write("\(JSGlueVariableScope.reservedI32Stack).push(\(value));") + } + func emitPushF64Parameter(_ value: String, printer: CodeFragmentPrinter) { + printer.write("\(JSGlueVariableScope.reservedF64Stack).push(\(value));") + } + func emitPushF32Parameter(_ value: String, printer: CodeFragmentPrinter) { + printer.write("\(JSGlueVariableScope.reservedF32Stack).push(\(value));") + } + func emitPushPointerParameter(_ value: String, printer: CodeFragmentPrinter) { + printer.write("\(JSGlueVariableScope.reservedPointerStack).push(\(value));") + } + + // MARK: Return + + func emitPushI32Return(_ value: String, printer: CodeFragmentPrinter) { + printer.write("\(JSGlueVariableScope.reservedI32Stack).push(\(value));") + } + func emitPushF64Return(_ value: String, printer: CodeFragmentPrinter) { + printer.write("\(JSGlueVariableScope.reservedF64Stack).push(\(value));") + } + func emitPushPointerReturn(_ value: String, printer: CodeFragmentPrinter) { + printer.write("\(JSGlueVariableScope.reservedPointerStack).push(\(value));") + } + func popString() -> String { + return "\(JSGlueVariableScope.reservedStringStack).pop()" + } + func popI32() -> String { + return "\(JSGlueVariableScope.reservedI32Stack).pop()" + } + func popF64() -> String { + return "\(JSGlueVariableScope.reservedF64Stack).pop()" + } + func popF32() -> String { + return "\(JSGlueVariableScope.reservedF32Stack).pop()" + } + func popPointer() -> String { + return "\(JSGlueVariableScope.reservedPointerStack).pop()" + } +} + +/// A fragment of JS code used to convert a value between Swift and JS. +/// +/// See `BridgeJSIntrinsics.swift` in the main JavaScriptKit module for Swift side lowering/lifting implementation. +struct IntrinsicJSFragment: Sendable { + + struct PrintCodeContext { + /// The scope of the variables. + var scope: JSGlueVariableScope + /// The printer to print the main fragment code. + var printer: CodeFragmentPrinter + /// The printer to print the code that is expected to be executed at the end of the caller of the fragment. + var cleanupCode: CodeFragmentPrinter + /// Whether the fragment has direct access to the SwiftHeapObject classes. + /// If false, the fragment needs to use `_exports[""]` to access the class. + var hasDirectAccessToSwiftClass: Bool = true + + func with(_ keyPath: WritableKeyPath, _ value: T) -> PrintCodeContext { + var new = self + new[keyPath: keyPath] = value + return new + } + } + + /// A function that prints the fragment code. + /// + /// - Parameters: + /// - arguments: The arguments that the fragment expects. An argument may be an expression with side effects, + /// so the callee is responsible for evaluating the arguments only once. + /// - context: The context of the printing. + /// - Returns: List of result expressions. + typealias PrintCode = + @Sendable ( + _ arguments: [String], + _ context: PrintCodeContext + ) throws -> [String] + + /// The names of the parameters that the fragment expects. + let parameters: [String] + + /// Prints the fragment code. + let printCode: PrintCode + + init(parameters: [String], printCode: @escaping PrintCode) { + self.parameters = parameters + self.printCode = printCode + } + + func printCode(_ arguments: [String], _ context: PrintCodeContext) throws -> [String] { + return try printCode(arguments, context) + } + + /// A fragment that does nothing + static let void = IntrinsicJSFragment( + parameters: [], + printCode: { _, _ in + return [] + } + ) + + /// A fragment that returns the argument as is. + static let identity = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, _ in + return [arguments[0]] + } + ) + + /// NOTE: JavaScript engine itself converts booleans to integers when passing them to + /// Wasm functions, so we don't need to do anything here + static let boolLowerParameter = identity + static let boolLiftReturn = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, _ in + return ["\(arguments[0]) !== 0"] + } + ) + static let boolLiftParameter = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, _ in + return ["\(arguments[0]) !== 0"] + } + ) + static let boolLowerReturn = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, _ in + return ["\(arguments[0]) ? 1 : 0"] + } + ) + + /// Convert signed Int32 to unsigned for UInt values + static let uintLiftReturn = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, _ in + return ["\(arguments[0]) >>> 0"] + } + ) + static let uintLiftParameter = uintLiftReturn + + static let stringLowerParameter = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let argument = arguments[0] + let bytesLabel = scope.variable("\(argument)Bytes") + let bytesIdLabel = scope.variable("\(argument)Id") + printer.write("const \(bytesLabel) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(argument));") + printer.write("const \(bytesIdLabel) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesLabel));") + return [bytesIdLabel, "\(bytesLabel).length"] + } + ) + static let stringLiftReturn = IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let resultLabel = scope.variable("ret") + printer.write("const \(resultLabel) = \(JSGlueVariableScope.reservedStorageToReturnString);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") + return [resultLabel] + } + ) + static let stringLiftParameter = IntrinsicJSFragment( + parameters: ["objectId"], + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let objectId = arguments[0] + let objectLabel = scope.variable("\(objectId)Object") + // TODO: Implement "take" operation + printer.write("const \(objectLabel) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(objectId));") + printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(objectId));") + return [objectLabel] + } + ) + static let stringLowerReturn = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + printer.write( + "\(JSGlueVariableScope.reservedStorageToReturnBytes) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(arguments[0]));" + ) + return ["\(JSGlueVariableScope.reservedStorageToReturnBytes).length"] + } + ) + + static let jsObjectLowerParameter = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, _ in + return ["swift.memory.retain(\(arguments[0]))"] + } + ) + static let jsObjectLiftReturn = IntrinsicJSFragment( + parameters: ["retId"], + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + // TODO: Implement "take" operation + let resultLabel = scope.variable("ret") + let retId = arguments[0] + printer.write("const \(resultLabel) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(retId));") + printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(retId));") + return [resultLabel] + } + ) + static let jsObjectLiftRetainedObjectId = IntrinsicJSFragment( + parameters: ["objectId"], + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let resultLabel = scope.variable("value") + let objectId = arguments[0] + printer.write( + "const \(resultLabel) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(objectId));" + ) + printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(objectId));") + return [resultLabel] + } + ) + static let jsObjectLiftParameter = IntrinsicJSFragment( + parameters: ["objectId"], + printCode: { arguments, _ in + return ["\(JSGlueVariableScope.reservedSwift).memory.getObject(\(arguments[0]))"] + } + ) + static let jsObjectLowerReturn = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, _ in + return ["\(JSGlueVariableScope.reservedSwift).memory.retain(\(arguments[0]))"] + } + ) + + private static let jsValueLowerHelperName = "__bjs_jsValueLower" + private static let jsValueLiftHelperName = "__bjs_jsValueLift" + + private static func registerJSValueHelpers(scope: JSGlueVariableScope) { + scope.registerIntrinsic("jsValueHelpers") { helperPrinter in + helperPrinter.write("function \(jsValueLowerHelperName)(value) {") + helperPrinter.indent { + emitJSValueLowerBody( + value: "value", + kindVar: "kind", + payload1Var: "payload1", + payload2Var: "payload2", + printer: helperPrinter + ) + helperPrinter.write("return [kind, payload1, payload2];") + } + helperPrinter.write("}") + helperPrinter.write("function \(jsValueLiftHelperName)(kind, payload1, payload2) {") + helperPrinter.indent { + let helperScope = scope.makeChildScope() + let resultVar = emitJSValueConstruction( + kind: "kind", + payload1: "payload1", + payload2: "payload2", + scope: helperScope, + printer: helperPrinter + ) + helperPrinter.write("return \(resultVar);") + } + helperPrinter.write("}") + } + } + + private static func emitJSValueLowerBody( + value: String, + kindVar: String, + payload1Var: String, + payload2Var: String, + printer: CodeFragmentPrinter + ) { + printer.write("let \(kindVar);") + printer.write("let \(payload1Var);") + printer.write("let \(payload2Var);") + printer.write("if (\(value) === null) {") + printer.indent { + printer.write("\(kindVar) = 4;") + printer.write("\(payload1Var) = 0;") + printer.write("\(payload2Var) = 0;") + } + printer.write("} else {") + printer.indent { + printer.write("switch (typeof \(value)) {") + printer.indent { + printer.write("case \"boolean\":") + printer.indent { + printer.write("\(kindVar) = 0;") + printer.write("\(payload1Var) = \(value) ? 1 : 0;") + printer.write("\(payload2Var) = 0;") + printer.write("break;") + } + printer.write("case \"number\":") + printer.indent { + printer.write("\(kindVar) = 2;") + printer.write("\(payload1Var) = 0;") + printer.write("\(payload2Var) = \(value);") + printer.write("break;") + } + printer.write("case \"string\":") + printer.indent { + printer.write("\(kindVar) = 1;") + printer.write("\(payload1Var) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + printer.write("\(payload2Var) = 0;") + printer.write("break;") + } + printer.write("case \"undefined\":") + printer.indent { + printer.write("\(kindVar) = 5;") + printer.write("\(payload1Var) = 0;") + printer.write("\(payload2Var) = 0;") + printer.write("break;") + } + printer.write("case \"object\":") + printer.indent { + printer.write("\(kindVar) = 3;") + printer.write("\(payload1Var) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + printer.write("\(payload2Var) = 0;") + printer.write("break;") + } + printer.write("case \"function\":") + printer.indent { + printer.write("\(kindVar) = 3;") + printer.write("\(payload1Var) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + printer.write("\(payload2Var) = 0;") + printer.write("break;") + } + printer.write("case \"symbol\":") + printer.indent { + printer.write("\(kindVar) = 7;") + printer.write("\(payload1Var) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + printer.write("\(payload2Var) = 0;") + printer.write("break;") + } + printer.write("case \"bigint\":") + printer.indent { + printer.write("\(kindVar) = 8;") + printer.write("\(payload1Var) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + printer.write("\(payload2Var) = 0;") + printer.write("break;") + } + printer.write("default:") + printer.indent { + printer.write("throw new TypeError(\"Unsupported JSValue type\");") + } + } + printer.write("}") + } + printer.write("}") + } + + static let jsValueLower = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let value = arguments[0] + let kindVar = scope.variable("\(value)Kind") + let payload1Var = scope.variable("\(value)Payload1") + let payload2Var = scope.variable("\(value)Payload2") + registerJSValueHelpers(scope: scope) + printer.write( + "const [\(kindVar), \(payload1Var), \(payload2Var)] = \(jsValueLowerHelperName)(\(value));" + ) + return [kindVar, payload1Var, payload2Var] + } + ) + + private static func emitJSValueConstruction( + kind: String, + payload1: String, + payload2: String, + scope: JSGlueVariableScope, + printer: CodeFragmentPrinter + ) -> String { + let resultVar = scope.variable("jsValue") + printer.write("let \(resultVar);") + printer.write("switch (\(kind)) {") + printer.indent { + printer.write("case 0:") + printer.indent { + printer.write("\(resultVar) = \(payload1) !== 0;") + printer.write("break;") + } + printer.write("case 1:") + printer.indent { + printer.write( + "\(resultVar) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(payload1));" + ) + printer.write("break;") + } + printer.write("case 2:") + printer.indent { + printer.write("\(resultVar) = \(payload2);") + printer.write("break;") + } + printer.write("case 3:") + printer.indent { + printer.write( + "\(resultVar) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(payload1));" + ) + printer.write("break;") + } + printer.write("case 4:") + printer.indent { + printer.write("\(resultVar) = null;") + printer.write("break;") + } + printer.write("case 5:") + printer.indent { + printer.write("\(resultVar) = undefined;") + printer.write("break;") + } + printer.write("case 7:") + printer.indent { + printer.write( + "\(resultVar) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(payload1));" + ) + printer.write("break;") + } + printer.write("case 8:") + printer.indent { + printer.write( + "\(resultVar) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(payload1));" + ) + printer.write("break;") + } + printer.write("default:") + printer.indent { + printer.write("throw new TypeError(\"Unsupported JSValue kind \" + \(kind));") + } + } + printer.write("}") + return resultVar + } + + static func jsValueLowerReturn(context: BridgeContext) -> IntrinsicJSFragment { + switch context { + case .importTS: + // Return values from imported JS functions should be delivered to the Swift side + // via the parameter stacks that `_swift_js_pop_*` read from. + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let lowered = try jsValueLower.printCode(arguments, context) + let kindVar = lowered[0] + let payload1Var = lowered[1] + let payload2Var = lowered[2] + scope.emitPushI32Parameter(kindVar, printer: printer) + scope.emitPushI32Parameter(payload1Var, printer: printer) + scope.emitPushF64Parameter(payload2Var, printer: printer) + return [] + } + ) + case .exportSwift: + // Kept for symmetry, though JSValue return for export currently relies on Swift pushing + // to tmpRet stacks directly. + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let lowered = try jsValueLower.printCode( + arguments, + context + ) + let kindVar = lowered[0] + let payload1Var = lowered[1] + let payload2Var = lowered[2] + scope.emitPushI32Parameter(kindVar, printer: printer) + scope.emitPushI32Parameter(payload1Var, printer: printer) + scope.emitPushF64Parameter(payload2Var, printer: printer) + return [] + } + ) + } + } + + static let jsValueLift = IntrinsicJSFragment( + parameters: [], + printCode: { _, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let payload2 = scope.variable("jsValuePayload2") + let payload1 = scope.variable("jsValuePayload1") + let kind = scope.variable("jsValueKind") + printer.write("const \(payload2) = \(scope.popF64());") + printer.write("const \(payload1) = \(scope.popI32());") + printer.write("const \(kind) = \(scope.popI32());") + let resultVar = scope.variable("jsValue") + registerJSValueHelpers(scope: scope) + printer.write( + "const \(resultVar) = \(jsValueLiftHelperName)(\(kind), \(payload1), \(payload2));" + ) + return [resultVar] + } + ) + static let jsValueLiftParameter = IntrinsicJSFragment( + parameters: ["kind", "payload1", "payload2"], + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let resultVar = scope.variable("jsValue") + registerJSValueHelpers(scope: scope) + printer.write( + "const \(resultVar) = \(jsValueLiftHelperName)(\(arguments[0]), \(arguments[1]), \(arguments[2]));" + ) + return [resultVar] + } + ) + + static let swiftHeapObjectLowerParameter = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + return ["\(arguments[0]).pointer"] + } + ) + static func swiftHeapObjectLiftReturn(_ name: String) -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + return [ + "\(context.hasDirectAccessToSwiftClass ? name : "_exports['\(name)']").__construct(\(arguments[0]))" + ] + } + ) + } + static func swiftHeapObjectLiftParameter(_ name: String) -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["pointer"], + printCode: { arguments, context in + return ["_exports['\(name)'].__construct(\(arguments[0]))"] + } + ) + } + static let swiftHeapObjectLowerReturn = IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + return ["\(arguments[0]).pointer"] + } + ) + + static func associatedEnumLowerParameter(enumBase: String) -> IntrinsicJSFragment { + IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (printer, cleanup) = (context.printer, context.cleanupCode) + let value = arguments[0] + let caseIdName = "\(value)CaseId" + let cleanupName = "\(value)Cleanup" + printer.write( + "const { caseId: \(caseIdName), cleanup: \(cleanupName) } = \(JSGlueVariableScope.reservedEnumHelpers).\(enumBase).lower(\(value));" + ) + cleanup.write("if (\(cleanupName)) { \(cleanupName)(); }") + return [caseIdName] + } + ) + } + + static func associatedEnumLiftReturn(enumBase: String) -> IntrinsicJSFragment { + IntrinsicJSFragment( + parameters: [], + printCode: { _, context in + let (scope, printer) = (context.scope, context.printer) + let retName = scope.variable("ret") + printer.write( + "const \(retName) = \(JSGlueVariableScope.reservedEnumHelpers).\(enumBase).lift(\(scope.popI32()));" + ) + return [retName] + } + ) + } + + static func optionalLiftParameter(wrappedType: BridgeType, kind: JSOptionalKind) throws -> IntrinsicJSFragment { + if case .jsValue = wrappedType { + return IntrinsicJSFragment( + parameters: ["isSome", "kind", "payload1", "payload2"], + printCode: { arguments, context in + let isSome = arguments[0] + let lifted = try jsValueLiftParameter.printCode( + [arguments[1], arguments[2], arguments[3]], + context + ) + let valueExpr = lifted.first ?? "undefined" + return ["\(isSome) ? \(valueExpr) : null"] + } + ) + } + + return IntrinsicJSFragment( + parameters: ["isSome", "wrappedValue"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let isSome = arguments[0] + let wrappedValue = arguments[1] + let resultExpr: String + let absenceLiteral = kind.absenceLiteral + + switch wrappedType { + case .int, .float, .double, .caseEnum: + resultExpr = "\(isSome) ? \(wrappedValue) : \(absenceLiteral)" + case .bool: + resultExpr = "\(isSome) ? \(wrappedValue) !== 0 : \(absenceLiteral)" + case .string: + let objectLabel = scope.variable("obj") + printer.write("let \(objectLabel);") + printer.write("if (\(isSome)) {") + printer.indent { + printer.write( + "\(objectLabel) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(wrappedValue));" + ) + printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(wrappedValue));") + } + printer.write("}") + resultExpr = "\(isSome) ? \(objectLabel) : \(absenceLiteral)" + case .closure: + resultExpr = + "\(isSome) ? \(JSGlueVariableScope.reservedSwift).memory.getObject(\(wrappedValue)) : \(absenceLiteral)" + case .swiftHeapObject(let name): + resultExpr = "\(isSome) ? _exports['\(name)'].__construct(\(wrappedValue)) : \(absenceLiteral)" + case .jsObject: + resultExpr = + "\(isSome) ? \(JSGlueVariableScope.reservedSwift).memory.getObject(\(wrappedValue)) : \(absenceLiteral)" + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: + let objectLabel = scope.variable("obj") + printer.write("let \(objectLabel);") + printer.write("if (\(isSome)) {") + printer.indent { + printer.write( + "\(objectLabel) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(wrappedValue));" + ) + printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(wrappedValue));") + } + printer.write("}") + resultExpr = "\(isSome) ? \(objectLabel) : \(absenceLiteral)" + case .bool: + resultExpr = "\(isSome) ? \(wrappedValue) !== 0 : \(absenceLiteral)" + default: + resultExpr = "\(isSome) ? \(wrappedValue) : \(absenceLiteral)" + } + case .associatedValueEnum(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + let enumVar = scope.variable("enumValue") + printer.write("let \(enumVar);") + printer.write("if (\(isSome)) {") + printer.indent { + printer.write( + "\(enumVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(wrappedValue));" + ) + } + printer.write("}") + resultExpr = "\(isSome) ? \(enumVar) : \(absenceLiteral)" + case .swiftStruct(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + let structVar = scope.variable("structValue") + printer.write("let \(structVar);") + printer.write("if (\(isSome)) {") + printer.indent { + printer.write( + "\(structVar) = \(JSGlueVariableScope.reservedStructHelpers).\(base).lift();" + ) + } + printer.write("} else {") + printer.indent { + printer.write("\(structVar) = \(absenceLiteral);") + } + printer.write("}") + resultExpr = structVar + case .array(let elementType): + let arrayVar = scope.variable("arrayValue") + printer.write("let \(arrayVar);") + printer.write("if (\(isSome)) {") + try printer.indent { + let arrayLiftFragment = try arrayLift(elementType: elementType) + let liftResults = try arrayLiftFragment.printCode([], context) + if let liftResult = liftResults.first { + printer.write("\(arrayVar) = \(liftResult);") + } + } + printer.write("} else {") + printer.indent { + printer.write("\(arrayVar) = \(absenceLiteral);") + } + printer.write("}") + resultExpr = arrayVar + case .dictionary(let valueType): + let dictVar = scope.variable("dictValue") + printer.write("let \(dictVar);") + printer.write("if (\(isSome)) {") + try printer.indent { + let dictLiftFragment = try dictionaryLift(valueType: valueType) + let liftResults = try dictLiftFragment.printCode([], context) + if let liftResult = liftResults.first { + printer.write("\(dictVar) = \(liftResult);") + } + } + printer.write("} else {") + printer.indent { + printer.write("\(dictVar) = \(absenceLiteral);") + } + printer.write("}") + resultExpr = dictVar + default: + resultExpr = "\(isSome) ? \(wrappedValue) : \(absenceLiteral)" + } + + return [resultExpr] + } + ) + } + + static func optionalLowerParameter(wrappedType: BridgeType) throws -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let value = arguments[0] + let isSomeVar = scope.variable("isSome") + printer.write("const \(isSomeVar) = \(value) != null;") + + switch wrappedType { + case .swiftStruct(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + let cleanupVar = scope.variable("\(value)Cleanup") + printer.write("let \(cleanupVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + let resultVar = scope.variable("structResult") + printer.write( + "const \(resultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(base).lower(\(value));" + ) + printer.write("\(cleanupVar) = \(resultVar).cleanup;") + } + printer.write("}") + cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") + printer.write("\(JSGlueVariableScope.reservedI32Stack).push(+\(isSomeVar));") + return [] + case .string, .rawValueEnum(_, .string): + let bytesVar = scope.variable("\(value)Bytes") + let idVar = scope.variable("\(value)Id") + + printer.write("let \(idVar), \(bytesVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + printer.write("\(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));") + printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));") + } + printer.write("}") + return ["+\(isSomeVar)", "\(isSomeVar) ? \(idVar) : 0", "\(isSomeVar) ? \(bytesVar).length : 0"] + case .jsValue: + let lowered = try jsValueLower.printCode([value], context) + return ["+\(isSomeVar)"] + lowered + case .associatedValueEnum(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + let caseIdVar = scope.variable("\(value)CaseId") + let cleanupVar = scope.variable("\(value)Cleanup") + + printer.write("let \(caseIdVar), \(cleanupVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + let resultVar = scope.variable("enumResult") + printer.write( + "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(value));" + ) + printer.write("\(caseIdVar) = \(resultVar).caseId;") + printer.write("\(cleanupVar) = \(resultVar).cleanup;") + } + printer.write("}") + cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") + + return ["+\(isSomeVar)", "\(isSomeVar) ? \(caseIdVar) : 0"] + case .rawValueEnum: + // Raw value enums with optional - falls through to handle based on raw type + return ["+\(isSomeVar)", "\(isSomeVar) ? \(value) : 0"] + case .array(let elementType): + let cleanupArrayVar = scope.variable("\(value)Cleanups") + printer.write("const \(cleanupArrayVar) = [];") + printer.write("if (\(isSomeVar)) {") + try printer.indent { + let arrayLowerFragment = try arrayLower(elementType: elementType) + let arrayCleanup = CodeFragmentPrinter() + let _ = try arrayLowerFragment.printCode( + [value], + context.with(\.cleanupCode, arrayCleanup) + ) + if !arrayCleanup.lines.isEmpty { + for line in arrayCleanup.lines { + printer.write("\(cleanupArrayVar).push(() => { \(line) });") + } + } + } + printer.write("}") + cleanupCode.write("for (const cleanup of \(cleanupArrayVar)) { cleanup(); }") + printer.write("\(JSGlueVariableScope.reservedI32Stack).push(+\(isSomeVar));") + return [] + case .dictionary(let valueType): + let cleanupArrayVar = scope.variable("\(value)Cleanups") + printer.write("const \(cleanupArrayVar) = [];") + printer.write("if (\(isSomeVar)) {") + try printer.indent { + let dictLowerFragment = try dictionaryLower(valueType: valueType) + let dictCleanup = CodeFragmentPrinter() + let _ = try dictLowerFragment.printCode( + [value], + context.with(\.cleanupCode, dictCleanup) + ) + if !dictCleanup.lines.isEmpty { + for line in dictCleanup.lines { + printer.write("\(cleanupArrayVar).push(() => { \(line) });") + } + } + } + printer.write("}") + cleanupCode.write("for (const cleanup of \(cleanupArrayVar)) { cleanup(); }") + printer.write("\(JSGlueVariableScope.reservedI32Stack).push(+\(isSomeVar));") + return [] + default: + switch wrappedType { + case .swiftHeapObject: + return ["+\(isSomeVar)", "\(isSomeVar) ? \(value).pointer : 0"] + case .swiftProtocol: + return [ + "+\(isSomeVar)", + "\(isSomeVar) ? \(JSGlueVariableScope.reservedSwift).memory.retain(\(value)) : 0", + ] + case .jsObject: + let idVar = scope.variable("id") + printer.write("let \(idVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + } + printer.write("}") + return ["+\(isSomeVar)", "\(isSomeVar) ? \(idVar) : 0"] + default: + return ["+\(isSomeVar)", "\(isSomeVar) ? \(value) : 0"] + } + } + } + ) + } + + static func optionalLiftReturn( + wrappedType: BridgeType, + kind: JSOptionalKind + ) -> IntrinsicJSFragment { + let absenceLiteral = kind.absenceLiteral + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let resultVar = scope.variable("optResult") + switch wrappedType { + case .bool: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalBool);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalBool) = undefined;") + case .int, .uint: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalInt);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = undefined;") + case .float: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalFloat);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = undefined;") + case .double: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalDouble);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = undefined;") + case .string: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnString);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") + case .jsObject, .swiftProtocol: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnString);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") + case .swiftHeapObject(let className): + let pointerVar = scope.variable("pointer") + printer.write( + "const \(pointerVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject);" + ) + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject) = undefined;") + let constructExpr = + context.hasDirectAccessToSwiftClass + ? "\(className).__construct(\(pointerVar))" + : "_exports['\(className)'].__construct(\(pointerVar))" + printer.write( + "const \(resultVar) = \(pointerVar) === null ? \(absenceLiteral) : \(constructExpr);" + ) + case .caseEnum: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalInt);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = undefined;") + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnString);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") + case .bool: + printer.write( + "const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalBool);" + ) + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalBool) = undefined;") + case .float: + printer.write( + "const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalFloat);" + ) + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = undefined;") + case .double: + printer.write( + "const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalDouble);" + ) + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = undefined;") + default: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalInt);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = undefined;") + } + case .associatedValueEnum(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + let tagVar = scope.variable("tag") + printer.write("const \(tagVar) = \(scope.popI32());") + let isNullVar = scope.variable("isNull") + printer.write("const \(isNullVar) = (\(tagVar) === -1);") + printer.write("let \(resultVar);") + printer.write("if (\(isNullVar)) {") + printer.indent { + printer.write("\(resultVar) = \(absenceLiteral);") + } + printer.write("} else {") + printer.indent { + printer.write( + "\(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(tagVar));" + ) + } + printer.write("}") + case .swiftStruct(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + let isSomeVar = scope.variable("isSome") + printer.write("const \(isSomeVar) = \(scope.popI32());") + printer.write("let \(resultVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + printer.write( + "\(resultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(base).lift();" + ) + } + printer.write("} else {") + printer.indent { + printer.write("\(resultVar) = \(absenceLiteral);") + } + printer.write("}") + case .array(let elementType): + let isSomeVar = scope.variable("isSome") + printer.write("const \(isSomeVar) = \(scope.popI32());") + printer.write("let \(resultVar);") + printer.write("if (\(isSomeVar)) {") + try printer.indent { + let arrayLiftFragment = try arrayLift(elementType: elementType) + let liftResults = try arrayLiftFragment.printCode([], context) + if let liftResult = liftResults.first { + printer.write("\(resultVar) = \(liftResult);") + } + } + printer.write("} else {") + printer.indent { + printer.write("\(resultVar) = \(absenceLiteral);") + } + printer.write("}") + case .dictionary(let valueType): + let isSomeVar = scope.variable("isSome") + printer.write("const \(isSomeVar) = \(scope.popI32());") + printer.write("let \(resultVar);") + printer.write("if (\(isSomeVar)) {") + try printer.indent { + let dictLiftFragment = try dictionaryLift(valueType: valueType) + let liftResults = try dictLiftFragment.printCode([], context) + if let liftResult = liftResults.first { + printer.write("\(resultVar) = \(liftResult);") + } + } + printer.write("} else {") + printer.indent { + printer.write("\(resultVar) = \(absenceLiteral);") + } + printer.write("}") + case .jsValue: + let isSomeVar = scope.variable("isSome") + printer.write("const \(isSomeVar) = \(scope.popI32());") + printer.write("let \(resultVar);") + printer.write("if (\(isSomeVar)) {") + try printer.indent { + let lifted = try jsValueLift.printCode([], context) + if let liftedValue = lifted.first { + printer.write("\(resultVar) = \(liftedValue);") + } + } + printer.write("} else {") + printer.indent { + printer.write("\(resultVar) = null;") + } + printer.write("}") + default: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnString);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") + } + return [resultVar] + } + ) + } + + static func optionalLowerReturn(wrappedType: BridgeType, kind: JSOptionalKind) throws -> IntrinsicJSFragment { + switch wrappedType { + case .void, .nullable, .namespaceEnum, .closure: + throw BridgeJSLinkError(message: "Unsupported optional wrapped type for protocol export: \(wrappedType)") + default: break + } + + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let value = arguments[0] + let isSomeVar = scope.variable("isSome") + let presenceExpr = kind.presenceCheck(value: value) + printer.write("const \(isSomeVar) = \(presenceExpr);") + + switch wrappedType { + case .bool: + printer.write( + "bjs[\"swift_js_return_optional_bool\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? (\(value) ? 1 : 0) : 0);" + ) + case .int, .uint: + printer.write( + "bjs[\"swift_js_return_optional_int\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? (\(value) | 0) : 0);" + ) + case .caseEnum: + printer.write("return \(isSomeVar) ? (\(value) | 0) : -1;") + case .float: + printer.write( + "bjs[\"swift_js_return_optional_float\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? Math.fround(\(value)) : 0.0);" + ) + case .double: + printer.write( + "bjs[\"swift_js_return_optional_double\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? \(value) : 0.0);" + ) + case .string: + printer.write("if (\(isSomeVar)) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = \(value);") + } + printer.write("} else {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = null;") + } + printer.write("}") + case .jsObject, .swiftProtocol: + let idVar = scope.variable("id") + printer.write("let \(idVar) = 0;") + printer.write("if (\(isSomeVar)) {") + printer.indent { + printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + } + printer.write("}") + printer.write("bjs[\"swift_js_return_optional_object\"](\(isSomeVar) ? 1 : 0, \(idVar));") + case .jsValue: + if value != "undefined" { + let lowered = try jsValueLower.printCode([value], context) + let kindVar = lowered[0] + let payload1Var = lowered[1] + let payload2Var = lowered[2] + scope.emitPushI32Parameter(kindVar, printer: printer) + scope.emitPushI32Parameter(payload1Var, printer: printer) + scope.emitPushF64Parameter(payload2Var, printer: printer) + } + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + case .swiftHeapObject: + printer.write("return \(isSomeVar) ? \(value).pointer : 0;") + case .array(let elementType): + printer.write("if (\(isSomeVar)) {") + try printer.indent { + let arrayLowerFragment = try arrayLower(elementType: elementType) + let arrayCleanup = CodeFragmentPrinter() + let _ = try arrayLowerFragment.printCode( + [value], + context.with(\.cleanupCode, arrayCleanup) + ) + if !arrayCleanup.lines.isEmpty { + for line in arrayCleanup.lines { + printer.write(line) + } + } + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: + printer.write("if (\(isSomeVar)) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = \(value);") + } + printer.write("} else {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = null;") + } + printer.write("}") + default: + switch rawType { + case .bool: + printer.write( + "bjs[\"swift_js_return_optional_bool\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? (\(value) ? 1 : 0) : 0);" + ) + case .float: + printer.write( + "bjs[\"swift_js_return_optional_float\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? Math.fround(\(value)) : 0.0);" + ) + case .double: + printer.write( + "bjs[\"swift_js_return_optional_double\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? \(value) : 0.0);" + ) + default: + printer.write( + "bjs[\"swift_js_return_optional_int\"](\(isSomeVar) ? 1 : 0, \(isSomeVar) ? (\(value) | 0) : 0);" + ) + } + } + case .associatedValueEnum(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + let caseIdVar = scope.variable("caseId") + let cleanupVar = scope.variable("cleanup") + printer.write("if (\(isSomeVar)) {") + printer.indent { + printer.write( + "const { caseId: \(caseIdVar), cleanup: \(cleanupVar) } = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(value));" + ) + printer.write("return \(caseIdVar);") + } + printer.write("} else {") + printer.indent { + printer.write("return -1;") + } + printer.write("}") + cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") + case .dictionary(let valueType): + printer.write("if (\(isSomeVar)) {") + try printer.indent { + let cleanupArrayVar = scope.variable("arrayCleanups") + let entriesVar = scope.variable("entries") + let entryVar = scope.variable("entry") + printer.write("const \(cleanupArrayVar) = [];") + printer.write("const \(entriesVar) = Object.entries(\(value));") + printer.write("for (const \(entryVar) of \(entriesVar)) {") + try printer.indent { + let keyVar = scope.variable("key") + let valueVar = scope.variable("value") + printer.write("const [\(keyVar), \(valueVar)] = \(entryVar);") + + let keyFragment = try stackLowerFragment(elementType: .string) + let keyCleanup = CodeFragmentPrinter() + let _ = try keyFragment.printCode( + [keyVar], + context.with(\.cleanupCode, keyCleanup) + ) + if !keyCleanup.lines.isEmpty { + printer.write("\(cleanupArrayVar).push(() => {") + printer.indent { + for line in keyCleanup.lines { + printer.write(line) + } + } + printer.write("});") + } + + let valueFragment = try stackLowerFragment(elementType: valueType) + let valueCleanup = CodeFragmentPrinter() + let _ = try valueFragment.printCode( + [valueVar], + context.with(\.cleanupCode, valueCleanup) + ) + if !valueCleanup.lines.isEmpty { + printer.write("\(cleanupArrayVar).push(() => {") + printer.indent { + for line in valueCleanup.lines { + printer.write(line) + } + } + printer.write("});") + } + } + printer.write("}") + scope.emitPushI32Parameter("\(entriesVar).length", printer: printer) + cleanupCode.write("for (const cleanup of \(cleanupArrayVar)) { cleanup(); }") + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + default: + throw BridgeJSLinkError( + message: "Unsupported wrapped type for returning from JS function: \(wrappedType)" + ) + } + + return [] + } + ) + } + + // MARK: - Protocol Support + + static func protocolPropertyOptionalToSideChannel(wrappedType: BridgeType) throws -> IntrinsicJSFragment { + switch wrappedType { + case .string, .int, .float, .double, .jsObject, .swiftProtocol: + break + case .rawValueEnum(_, let rawType): + switch rawType { + case .string, .int, .float, .double: + break + default: + throw BridgeJSLinkError( + message: "Unsupported raw value enum type for protocol property side channel: \(rawType)" + ) + } + default: + throw BridgeJSLinkError( + message: "Type \(wrappedType) does not use side channel for protocol property returns" + ) + } + + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let printer = context.printer + let value = arguments[0] + + switch wrappedType { + case .string, .rawValueEnum(_, .string): + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = \(value);") + case .int, .rawValueEnum(_, .int): + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = \(value);") + case .float, .rawValueEnum(_, .float): + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = \(value);") + case .double, .rawValueEnum(_, .double): + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = \(value);") + case .jsObject, .swiftProtocol: + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = \(value);") + default: + fatalError("Unsupported type in protocolPropertyOptionalToSideChannel: \(wrappedType)") + } + + return [] + } + ) + } + + // MARK: - ExportSwift + + /// Returns a fragment that lowers a JS value to Wasm core values for parameters + static func lowerParameter(type: BridgeType) throws -> IntrinsicJSFragment { + switch type { + case .int, .uint, .float, .double, .bool, .unsafePointer: return .identity + case .string: return .stringLowerParameter + case .jsObject: return .jsObjectLowerParameter + case .jsValue: return .jsValueLower + case .swiftHeapObject: + return .swiftHeapObjectLowerParameter + case .swiftProtocol: return .jsObjectLowerParameter + case .void: return .void + case .nullable(let wrappedType, _): + return try .optionalLowerParameter(wrappedType: wrappedType) + case .caseEnum: return .identity + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: return .stringLowerParameter + default: return .identity + } + case .associatedValueEnum(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + return .associatedEnumLowerParameter(enumBase: base) + case .swiftStruct(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + return swiftStructLowerParameter(structBase: base) + case .closure: + return IntrinsicJSFragment( + parameters: ["closure"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let closure = arguments[0] + let callbackIdVar = scope.variable("callbackId") + printer.write( + "const \(callbackIdVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(closure));" + ) + return [callbackIdVar] + } + ) + 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) + case .dictionary(let valueType): + return try dictionaryLower(valueType: valueType) + } + } + + /// Returns a fragment that lifts a Wasm core value to a JS value for return values + static func liftReturn(type: BridgeType) throws -> IntrinsicJSFragment { + switch type { + case .int, .float, .double: return .identity + case .uint: return .uintLiftReturn + case .bool: return .boolLiftReturn + case .string: return .stringLiftReturn + case .jsObject: return .jsObjectLiftReturn + case .jsValue: return .jsValueLift + case .swiftHeapObject(let name): return .swiftHeapObjectLiftReturn(name) + case .unsafePointer: return .identity + case .swiftProtocol: return .jsObjectLiftReturn + case .void: return .void + case .nullable(let wrappedType, let kind): + return .optionalLiftReturn(wrappedType: wrappedType, kind: kind) + case .caseEnum: return .identity + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: return .stringLiftReturn + case .bool: return .boolLiftReturn + default: return .identity + } + case .associatedValueEnum(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + return .associatedEnumLiftReturn(enumBase: base) + case .swiftStruct(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + return swiftStructLiftReturn(structBase: base) + case .closure: + return IntrinsicJSFragment( + parameters: ["funcRef"], + printCode: { arguments, context in + let funcRef = arguments[0] + return ["\(JSGlueVariableScope.reservedSwift).memory.getObject(\(funcRef))"] + } + ) + case .namespaceEnum(let string): + throw BridgeJSLinkError( + message: "Namespace enums are not supported to be returned from functions: \(string)" + ) + case .array(let elementType): + return try arrayLift(elementType: elementType) + case .dictionary(let valueType): + return try dictionaryLift(valueType: valueType) + } + } + + // MARK: - ImportedJS + + /// Returns a fragment that lifts Wasm core values to JS values for parameters + 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 .jsValue: return .jsValueLiftParameter + case .unsafePointer: return .identity + case .swiftHeapObject(let name): + return .swiftHeapObjectLiftParameter(name) + case .swiftProtocol: return .jsObjectLiftParameter + case .void: + throw BridgeJSLinkError( + message: "Void can't appear in parameters of imported JS functions" + ) + case .nullable(let wrappedType, let kind): + return try .optionalLiftParameter(wrappedType: wrappedType, kind: kind) + case .caseEnum: return .identity + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: return .stringLiftParameter + case .bool: return .boolLiftParameter + default: return .identity + } + case .associatedValueEnum(let fullName): + switch context { + case .importTS: + throw BridgeJSLinkError( + message: + "Associated value enums are not supported to be passed as parameters to imported JS functions: \(fullName)" + ) + case .exportSwift: + let base = fullName.components(separatedBy: ".").last ?? fullName + return IntrinsicJSFragment( + parameters: ["caseId"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let caseId = arguments[0] + let resultVar = scope.variable("enumValue") + printer.write( + "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(caseId));" + ) + return [resultVar] + } + ) + } + case .swiftStruct(let fullName): + switch context { + case .importTS: + return .jsObjectLiftRetainedObjectId + case .exportSwift: + let base = fullName.components(separatedBy: ".").last ?? fullName + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let resultVar = scope.variable("structValue") + printer.write( + "const \(resultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(base).lift();" + ) + return [resultVar] + } + ) + } + case .closure: + return IntrinsicJSFragment( + parameters: ["funcRef"], + printCode: { arguments, context in + let funcRef = arguments[0] + return ["\(JSGlueVariableScope.reservedSwift).memory.getObject(\(funcRef))"] + } + ) + case .namespaceEnum(let string): + throw BridgeJSLinkError( + message: + "Namespace enums are not supported to be passed as parameters to imported JS functions: \(string)" + ) + case .array(let elementType): + return try arrayLift(elementType: elementType) + case .dictionary(let valueType): + return try dictionaryLift(valueType: valueType) + } + } + + /// 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, .uint, .float, .double: return .identity + case .bool: return .boolLowerReturn + case .string: return .stringLowerReturn + case .jsObject: return .jsObjectLowerReturn + case .jsValue: return .jsValueLowerReturn(context: context) + case .unsafePointer: return .identity + case .swiftHeapObject: + return .swiftHeapObjectLowerReturn + case .swiftProtocol: return .jsObjectLowerReturn + case .void: return .void + case .nullable(let wrappedType, let kind): + return try .optionalLowerReturn(wrappedType: wrappedType, kind: kind) + case .caseEnum: return .identity + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: return .stringLowerReturn + case .bool: return .boolLowerReturn + default: return .identity + } + case .associatedValueEnum(let fullName): + switch context { + case .importTS: + throw BridgeJSLinkError( + message: + "Associated value enums are not supported to be returned from imported JS functions: \(fullName)" + ) + case .exportSwift: + return associatedValueLowerReturn(fullName: fullName) + } + case .swiftStruct(let fullName): + switch context { + case .importTS: + // ImportTS expects Swift structs to come back as a retained JS object ID. + return .jsObjectLowerReturn + case .exportSwift: + return swiftStructLowerReturn(fullName: fullName) + } + case .closure: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let printer = context.printer + let value = arguments[0] + printer.write("if (typeof \(value) !== \"function\") {") + printer.indent { + printer.write("throw new TypeError(\"Expected a function\")") + } + printer.write("}") + return ["\(JSGlueVariableScope.reservedSwift).memory.retain(\(value))"] + } + ) + case .namespaceEnum(let string): + throw BridgeJSLinkError( + message: "Namespace enums are not supported to be returned from imported JS functions: \(string)" + ) + case .array(let elementType): + return try arrayLower(elementType: elementType) + case .dictionary(let valueType): + return try dictionaryLower(valueType: valueType) + } + } + + // MARK: - Enums Payload Fragments + + static func associatedValueLowerReturn(fullName: String) -> IntrinsicJSFragment { + let base = fullName.components(separatedBy: ".").last ?? fullName + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let value = arguments[0] + let caseIdVar = scope.variable("caseId") + let cleanupVar = scope.variable("cleanup") + printer.write( + "const { caseId: \(caseIdVar), cleanup: \(cleanupVar) } = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(value));" + ) + cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") + printer.write("return \(caseIdVar);") + return [] + } + ) + } + /// Fragment for generating an entire associated value enum helper + /// Generates the enum tag constants (e.g. `const XValues = { Tag: { ... } }`) + /// This is placed at module level for exports/imports. + static func associatedValueEnumValues(enumDefinition: ExportedEnum) -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["enumName"], + printCode: { arguments, context in + let printer = context.printer + let enumName = arguments[0] + + printer.write("const \(enumName) = {") + printer.indent { + printer.write("Tag: {") + printer.indent { + for (index, enumCase) in enumDefinition.cases.enumerated() { + let caseName = enumCase.name.capitalizedFirstLetter + printer.write("\(caseName): \(index),") + } + } + printer.write("},") + } + printer.write("};") + + return [] + } + ) + } + + /// Generates the enum helper factory function (lower/lift closures). + /// This is placed inside `createInstantiator` alongside struct helpers, + /// so it has access to `_exports` for class references. + static func associatedValueEnumHelperFactory(enumDefinition: ExportedEnum) -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["enumName"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let enumName = arguments[0] + + printer.write("const __bjs_create\(enumName)Helpers = () => {") + printer.indent() + printer.write( + "return () => ({" + ) + printer.indent() + + // Generate lower function + printer.write("lower: (value) => {") + try printer.indent { + printer.write("const enumTag = value.tag;") + printer.write("switch (enumTag) {") + try printer.indent { + let lowerPrinter = CodeFragmentPrinter() + for enumCase in enumDefinition.cases { + let caseName = enumCase.name.capitalizedFirstLetter + let caseScope = scope.makeChildScope() + let caseCleanup = CodeFragmentPrinter() + caseCleanup.indent() + let fragment = IntrinsicJSFragment.associatedValuePushPayload(enumCase: enumCase) + _ = try fragment.printCode( + ["value", enumName, caseName], + context.with(\.scope, caseScope).with(\.printer, lowerPrinter).with( + \.cleanupCode, + caseCleanup + ) + ) + } + + for line in lowerPrinter.lines { + printer.write(line) + } + + printer.write("default: throw new Error(\"Unknown \(enumName) tag: \" + String(enumTag));") + } + printer.write("}") + } + printer.write("},") + + // Generate lift function + printer.write( + "lift: (tag) => {" + ) + try printer.indent { + printer.write("tag = tag | 0;") + printer.write("switch (tag) {") + try printer.indent { + let liftPrinter = CodeFragmentPrinter() + for enumCase in enumDefinition.cases { + let caseName = enumCase.name.capitalizedFirstLetter + let caseScope = scope.makeChildScope() + let caseCleanup = CodeFragmentPrinter() + + let fragment = IntrinsicJSFragment.associatedValuePopPayload(enumCase: enumCase) + _ = try fragment.printCode( + [enumName, caseName], + context.with(\.scope, caseScope).with(\.printer, liftPrinter).with( + \.cleanupCode, + caseCleanup + ) + ) + } + + for line in liftPrinter.lines { + printer.write(line) + } + + printer.write( + "default: throw new Error(\"Unknown \(enumName) tag returned from Swift: \" + String(tag));" + ) + } + printer.write("}") + } + printer.write("}") + printer.unindent() + printer.write("});") + printer.unindent() + printer.write("};") + + return [] + } + ) + } + + static func simpleEnumHelper(enumDefinition: ExportedEnum) -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["enumName"], + printCode: { arguments, context in + let printer = context.printer + let enumName = arguments[0] + printer.write("const \(enumName) = {") + printer.indent { + for (index, enumCase) in enumDefinition.cases.enumerated() { + let caseName = enumCase.name.capitalizedFirstLetter + let value = enumCase.jsValue( + rawType: enumDefinition.rawType, + index: index + ) + printer.write("\(caseName): \(value),") + } + } + printer.write("};") + printer.nextLine() + + return [] + } + ) + } + + static func rawValueEnumHelper(enumDefinition: ExportedEnum) -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["enumName"], + printCode: { arguments, context in + let printer = context.printer + let enumName = arguments[0] + printer.write("const \(enumName) = {") + printer.indent { + for (index, enumCase) in enumDefinition.cases.enumerated() { + let caseName = enumCase.name.capitalizedFirstLetter + let value = enumCase.jsValue( + rawType: enumDefinition.rawType, + index: index + ) + printer.write("\(caseName): \(value),") + } + } + printer.write("};") + printer.nextLine() + + return [] + } + ) + } + + private static func associatedValuePushPayload(enumCase: EnumCase) -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["value", "enumName", "caseName"], + printCode: { arguments, context in + let (printer, cleanup) = (context.printer, context.cleanupCode) + let enumName = arguments[1] + let caseName = arguments[2] + + printer.write("case \(enumName).Tag.\(caseName): {") + + try printer.indent { + if enumCase.associatedValues.isEmpty { + printer.write("const cleanup = undefined;") + printer.write("return { caseId: \(enumName).Tag.\(caseName), cleanup };") + } else { + // Process associated values in reverse order (to match the order they'll be popped) + let reversedValues = enumCase.associatedValues.enumerated().reversed() + + for (associatedValueIndex, associatedValue) in reversedValues { + let prop = associatedValue.label ?? "param\(associatedValueIndex)" + let fragment = try IntrinsicJSFragment.associatedValuePushPayload( + type: associatedValue.type + ) + + _ = try fragment.printCode(["value.\(prop)"], context) + } + + if cleanup.lines.isEmpty { + printer.write("const cleanup = undefined;") + } else { + printer.write("const cleanup = () => {") + printer.write(contentsOf: cleanup) + printer.write("};") + } + printer.write("return { caseId: \(enumName).Tag.\(caseName), cleanup };") + } + } + + printer.write("}") + + return [] + } + ) + } + + private static func associatedValuePopPayload(enumCase: EnumCase) -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["enumName", "caseName"], + printCode: { arguments, context in + let printer = context.printer + let enumName = arguments[0] + let caseName = arguments[1] + + if enumCase.associatedValues.isEmpty { + printer.write("case \(enumName).Tag.\(caseName): return { tag: \(enumName).Tag.\(caseName) };") + } else { + var fieldPairs: [String] = [] + let casePrinter = CodeFragmentPrinter() + + // Process associated values in reverse order (to match the order they'll be popped) + for (associatedValueIndex, associatedValue) in enumCase.associatedValues.enumerated().reversed() { + let prop = associatedValue.label ?? "param\(associatedValueIndex)" + let fragment = try IntrinsicJSFragment.associatedValuePopPayload(type: associatedValue.type) + + let result = try fragment.printCode([], context.with(\.printer, casePrinter)) + let varName = result.first ?? "value_\(associatedValueIndex)" + + fieldPairs.append("\(prop): \(varName)") + } + + printer.write("case \(enumName).Tag.\(caseName): {") + printer.indent { + for line in casePrinter.lines { + printer.write(line) + } + printer.write( + "return { tag: \(enumName).Tag.\(caseName), \(fieldPairs.reversed().joined(separator: ", ")) };" + ) + } + printer.write("}") + } + + return [] + } + ) + } + + private static func associatedValuePushPayload(type: BridgeType) throws -> IntrinsicJSFragment { + switch type { + case .nullable(let wrappedType, let kind): + return associatedValueOptionalPushPayload(wrappedType: wrappedType, kind: kind) + default: + return try stackLowerFragment(elementType: type) + } + } + + private static func associatedValueOptionalPushPayload( + wrappedType: BridgeType, + kind: JSOptionalKind + ) -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) + let value = arguments[0] + let isSomeVar = scope.variable("isSome") + printer.write("const \(isSomeVar) = \(kind.presenceCheck(value: value));") + + switch wrappedType { + case .string: + let idVar = scope.variable("id") + printer.write("let \(idVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + let bytesVar = scope.variable("bytes") + printer.write( + "let \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));" + ) + printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));") + scope.emitPushI32Parameter("\(bytesVar).length", printer: printer) + scope.emitPushI32Parameter(idVar, printer: printer) + } + printer.write("} else {") + printer.indent { + scope.emitPushI32Parameter("0", printer: printer) + scope.emitPushI32Parameter("0", printer: printer) + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + case .int, .uint: + scope.emitPushI32Parameter("\(isSomeVar) ? (\(value) | 0) : 0", printer: printer) + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + case .bool: + scope.emitPushI32Parameter("\(isSomeVar) ? (\(value) ? 1 : 0) : 0", printer: printer) + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + case .float: + scope.emitPushF32Parameter("\(isSomeVar) ? Math.fround(\(value)) : 0.0", printer: printer) + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + case .double: + scope.emitPushF64Parameter("\(isSomeVar) ? \(value) : 0.0", printer: printer) + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + case .caseEnum: + scope.emitPushI32Parameter("\(isSomeVar) ? (\(value) | 0) : 0", printer: printer) + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: + let idVar = scope.variable("id") + printer.write("let \(idVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + let bytesVar = scope.variable("bytes") + printer.write( + "let \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));" + ) + printer.write( + "\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));" + ) + scope.emitPushI32Parameter("\(bytesVar).length", printer: printer) + scope.emitPushI32Parameter(idVar, printer: printer) + } + printer.write("} else {") + printer.indent { + scope.emitPushI32Parameter("0", printer: printer) + scope.emitPushI32Parameter("0", printer: printer) + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + case .float: + scope.emitPushF32Parameter("\(isSomeVar) ? Math.fround(\(value)) : 0.0", printer: printer) + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + case .double: + scope.emitPushF64Parameter("\(isSomeVar) ? \(value) : 0.0", printer: printer) + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + default: + scope.emitPushI32Parameter("\(isSomeVar) ? (\(value) | 0) : 0", printer: printer) + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + } + case .swiftStruct(let structName): + let structBase = structName.components(separatedBy: ".").last ?? structName + let nestedCleanupVar = scope.variable("nestedCleanup") + printer.write("let \(nestedCleanupVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + let structResultVar = scope.variable("structResult") + printer.write( + "const \(structResultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(structBase).lower(\(value));" + ) + printer.write("\(nestedCleanupVar) = \(structResultVar).cleanup;") + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + cleanup.write("if (\(nestedCleanupVar)) { \(nestedCleanupVar)(); }") + case .swiftHeapObject: + printer.write("if (\(isSomeVar)) {") + printer.indent { + scope.emitPushPointerParameter("\(value).pointer", printer: printer) + } + printer.write("} else {") + printer.indent { + scope.emitPushPointerParameter("0", printer: printer) + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + case .jsObject: + let idVar = scope.variable("id") + printer.write("let \(idVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + scope.emitPushI32Parameter(idVar, printer: printer) + } + printer.write("} else {") + printer.indent { + printer.write("\(idVar) = undefined;") + scope.emitPushI32Parameter("0", printer: printer) + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + case .associatedValueEnum(let enumName): + let base = enumName.components(separatedBy: ".").last ?? enumName + let caseIdVar = scope.variable("enumCaseId") + let enumCleanupVar = scope.variable("enumCleanup") + printer.write("let \(caseIdVar), \(enumCleanupVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + let enumResultVar = scope.variable("enumResult") + printer.write( + "const \(enumResultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(value));" + ) + printer.write("\(caseIdVar) = \(enumResultVar).caseId;") + printer.write("\(enumCleanupVar) = \(enumResultVar).cleanup;") + scope.emitPushI32Parameter(caseIdVar, printer: printer) + } + printer.write("} else {") + printer.indent { + scope.emitPushI32Parameter("0", printer: printer) + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + cleanup.write("if (\(enumCleanupVar)) { \(enumCleanupVar)(); }") + case .array(let elementType): + // Array cleanup references variables declared inside the if block, + // so capture cleanup into a variable declared at the outer scope. + let arrCleanupVar = scope.variable("arrCleanup") + printer.write("let \(arrCleanupVar);") + printer.write("if (\(isSomeVar)) {") + try printer.indent { + let localCleanup = CodeFragmentPrinter() + let arrFragment = try arrayLower(elementType: elementType) + _ = try arrFragment.printCode( + [value], + context.with(\.cleanupCode, localCleanup) + ) + let cleanupLines = localCleanup.lines.filter { + !$0.trimmingCharacters(in: .whitespaces).isEmpty + } + if !cleanupLines.isEmpty { + printer.write("\(arrCleanupVar) = () => {") + printer.indent { + for line in cleanupLines { + printer.write(line) + } + } + printer.write("};") + } + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + cleanup.write("if (\(arrCleanupVar)) { \(arrCleanupVar)(); }") + default: + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + } + + return [] + } + ) + } + + private static func associatedValuePopPayload(type: BridgeType) throws -> IntrinsicJSFragment { + switch type { + case .nullable(let wrappedType, let kind): + return associatedValueOptionalPopPayload(wrappedType: wrappedType, kind: kind) + default: + return try stackLiftFragment(elementType: type) + } + } + + private static func associatedValueOptionalPopPayload( + wrappedType: BridgeType, + kind: JSOptionalKind + ) -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let optVar = scope.variable("optional") + let isSomeVar = scope.variable("isSome") + + printer.write("const \(isSomeVar) = \(scope.popI32());") + printer.write("let \(optVar);") + printer.write("if (\(isSomeVar)) {") + try printer.indent { + // For optional associated value enums, Swift uses bridgeJSLowerParameter() + // which pushes caseId to i32Stack (same as bridgeJSLowerReturn()). + if case .associatedValueEnum(let fullName) = wrappedType { + let base = fullName.components(separatedBy: ".").last ?? fullName + let caseIdVar = scope.variable("caseId") + printer.write("const \(caseIdVar) = \(scope.popI32());") + printer.write( + "\(optVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(caseIdVar));" + ) + } else { + let wrappedFragment = try associatedValuePopPayload(type: wrappedType) + let wrappedResults = try wrappedFragment.printCode([], context) + if let wrappedResult = wrappedResults.first { + printer.write("\(optVar) = \(wrappedResult);") + } else { + printer.write("\(optVar) = undefined;") + } + } + } + printer.write("} else {") + printer.indent { + printer.write("\(optVar) = \(kind.absenceLiteral);") + } + printer.write("}") + + return [optVar] + } + ) + } + + static func swiftStructLowerReturn(fullName: String) -> IntrinsicJSFragment { + let base = fullName.components(separatedBy: ".").last ?? fullName + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let value = arguments[0] + let cleanupVar = scope.variable("cleanup") + printer.write( + "const { cleanup: \(cleanupVar) } = \(JSGlueVariableScope.reservedStructHelpers).\(base).lower(\(value));" + ) + cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") + return [] + } + ) + } + + static func swiftStructLowerParameter(structBase: String) -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let value = arguments[0] + let cleanupVar = scope.variable("cleanup") + printer.write( + "const { cleanup: \(cleanupVar) } = \(JSGlueVariableScope.reservedStructHelpers).\(structBase).lower(\(value));" + ) + cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") + return [] + } + ) + } + + static func swiftStructLiftReturn(structBase: String) -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let resultVar = scope.variable("structValue") + printer.write( + "const \(resultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(structBase).lift();" + ) + 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, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let arr = arguments[0] + let cleanupArrayVar = scope.variable("arrayCleanups") + + printer.write("const \(cleanupArrayVar) = [];") + let elemVar = scope.variable("elem") + printer.write("for (const \(elemVar) of \(arr)) {") + try printer.indent { + let elementFragment = try stackLowerFragment(elementType: elementType) + let elementCleanup = CodeFragmentPrinter() + let _ = try elementFragment.printCode( + [elemVar], + context.with(\.cleanupCode, elementCleanup) + ) + if !elementCleanup.lines.isEmpty { + printer.write("\(cleanupArrayVar).push(() => {") + printer.indent { + for line in elementCleanup.lines { + printer.write(line) + } + } + printer.write("});") + } + } + printer.write("}") + scope.emitPushI32Parameter("\(arr).length", printer: printer) + cleanupCode.write("for (const cleanup of \(cleanupArrayVar)) { cleanup(); }") + return [] + } + ) + } + + /// Lowers a dictionary from JS to Swift by iterating entries and pushing to stacks + static func dictionaryLower(valueType: BridgeType) throws -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["dict"], + printCode: { arguments, context in + let (scope, printer, cleanupCode) = (context.scope, context.printer, context.cleanupCode) + let dict = arguments[0] + let cleanupArrayVar = scope.variable("arrayCleanups") + + printer.write("const \(cleanupArrayVar) = [];") + let entriesVar = scope.variable("entries") + let entryVar = scope.variable("entry") + printer.write("const \(entriesVar) = Object.entries(\(dict));") + printer.write("for (const \(entryVar) of \(entriesVar)) {") + try printer.indent { + let keyVar = scope.variable("key") + let valueVar = scope.variable("value") + printer.write("const [\(keyVar), \(valueVar)] = \(entryVar);") + + let keyFragment = try stackLowerFragment(elementType: .string) + let keyCleanup = CodeFragmentPrinter() + let _ = try keyFragment.printCode( + [keyVar], + context.with(\.cleanupCode, keyCleanup) + ) + if !keyCleanup.lines.isEmpty { + printer.write("\(cleanupArrayVar).push(() => {") + printer.indent { + for line in keyCleanup.lines { + printer.write(line) + } + } + printer.write("});") + } + + let valueFragment = try stackLowerFragment(elementType: valueType) + let valueCleanup = CodeFragmentPrinter() + let _ = try valueFragment.printCode( + [valueVar], + context.with(\.cleanupCode, valueCleanup) + ) + if !valueCleanup.lines.isEmpty { + printer.write("\(cleanupArrayVar).push(() => {") + printer.indent { + for line in valueCleanup.lines { + printer.write(line) + } + } + printer.write("});") + } + } + printer.write("}") + scope.emitPushI32Parameter("\(entriesVar).length", printer: printer) + cleanupCode.write("for (const cleanup of \(cleanupArrayVar)) { cleanup(); }") + 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, context in + let (scope, printer) = (context.scope, context.printer) + let resultVar = scope.variable("arrayResult") + let lenVar = scope.variable("arrayLen") + let iVar = scope.variable("i") + + printer.write("const \(lenVar) = \(scope.popI32());") + printer.write("const \(resultVar) = [];") + printer.write("for (let \(iVar) = 0; \(iVar) < \(lenVar); \(iVar)++) {") + try printer.indent { + let elementFragment = try stackLiftFragment(elementType: elementType) + let elementResults = try elementFragment.printCode([], context) + if let elementExpr = elementResults.first { + printer.write("\(resultVar).push(\(elementExpr));") + } + } + printer.write("}") + printer.write("\(resultVar).reverse();") + return [resultVar] + } + ) + } + + /// Lifts a dictionary from Swift to JS by popping key/value pairs from stacks + static func dictionaryLift(valueType: BridgeType) throws -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let resultVar = scope.variable("dictResult") + let lenVar = scope.variable("dictLen") + let iVar = scope.variable("i") + + printer.write("const \(lenVar) = \(scope.popI32());") + printer.write("const \(resultVar) = {};") + printer.write("for (let \(iVar) = 0; \(iVar) < \(lenVar); \(iVar)++) {") + try printer.indent { + let valueFragment = try stackLiftFragment(elementType: valueType) + let valueResults = try valueFragment.printCode([], context) + let keyFragment = try stackLiftFragment(elementType: .string) + let keyResults = try keyFragment.printCode([], context) + if let keyExpr = keyResults.first, let valueExpr = valueResults.first { + printer.write("\(resultVar)[\(keyExpr)] = \(valueExpr);") + } + } + printer.write("}") + return [resultVar] + } + ) + } + + private static func stackLiftFragment(elementType: BridgeType) throws -> IntrinsicJSFragment { + switch elementType { + case .jsValue: + return IntrinsicJSFragment( + parameters: [], + printCode: { _, context in + let (scope, printer) = (context.scope, context.printer) + let payload2Var = scope.variable("jsValuePayload2") + let payload1Var = scope.variable("jsValuePayload1") + let kindVar = scope.variable("jsValueKind") + printer.write("const \(payload2Var) = \(scope.popF64());") + printer.write("const \(payload1Var) = \(scope.popI32());") + printer.write("const \(kindVar) = \(scope.popI32());") + let resultVar = scope.variable("jsValue") + registerJSValueHelpers(scope: scope) + printer.write( + "const \(resultVar) = \(jsValueLiftHelperName)(\(kindVar), \(payload1Var), \(payload2Var));" + ) + return [resultVar] + } + ) + case .string: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let strVar = scope.variable("string") + printer.write("const \(strVar) = \(scope.popString());") + return [strVar] + } + ) + case .bool: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let bVar = scope.variable("bool") + printer.write("const \(bVar) = \(scope.popI32()) !== 0;") + return [bVar] + } + ) + case .int, .uint: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let iVar = scope.variable("int") + printer.write("const \(iVar) = \(scope.popI32());") + return [iVar] + } + ) + case .float: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let fVar = scope.variable("f32") + printer.write("const \(fVar) = \(scope.popF32());") + return [fVar] + } + ) + case .double: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let dVar = scope.variable("f64") + printer.write("const \(dVar) = \(scope.popF64());") + return [dVar] + } + ) + case .swiftStruct(let fullName): + let structBase = fullName.components(separatedBy: ".").last ?? fullName + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let resultVar = scope.variable("struct") + printer.write( + "const \(resultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(structBase).lift();" + ) + return [resultVar] + } + ) + case .caseEnum: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let varName = scope.variable("caseId") + printer.write("const \(varName) = \(scope.popI32());") + return [varName] + } + ) + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let varName = scope.variable("rawValue") + printer.write("const \(varName) = \(scope.popString());") + return [varName] + } + ) + case .float: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let varName = scope.variable("rawValue") + printer.write("const \(varName) = \(scope.popF32());") + return [varName] + } + ) + case .double: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let varName = scope.variable("rawValue") + printer.write("const \(varName) = \(scope.popF64());") + return [varName] + } + ) + default: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let varName = scope.variable("rawValue") + printer.write("const \(varName) = \(scope.popI32());") + return [varName] + } + ) + } + case .associatedValueEnum(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let resultVar = scope.variable("enumValue") + printer.write( + "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(scope.popI32()), );" + ) + return [resultVar] + } + ) + case .swiftHeapObject(let className): + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let ptrVar = scope.variable("ptr") + let objVar = scope.variable("obj") + printer.write("const \(ptrVar) = \(scope.popPointer());") + printer.write("const \(objVar) = _exports['\(className)'].__construct(\(ptrVar));") + return [objVar] + } + ) + case .jsObject, .swiftProtocol: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let idVar = scope.variable("objId") + let objVar = scope.variable("obj") + printer.write("const \(idVar) = \(scope.popI32());") + 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 .dictionary(let valueType): + return try dictionaryLift(valueType: valueType) + case .nullable(let wrappedType, let kind): + return try optionalElementRaiseFragment(wrappedType: wrappedType, kind: kind) + case .unsafePointer: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let pVar = scope.variable("pointer") + printer.write("const \(pVar) = \(scope.popPointer());") + return [pVar] + } + ) + case .void, .closure, .namespaceEnum: + throw BridgeJSLinkError(message: "Unsupported array element type: \(elementType)") + } + } + + private static func stackLowerFragment(elementType: BridgeType) throws -> IntrinsicJSFragment { + switch elementType { + case .jsValue: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + registerJSValueHelpers(scope: scope) + let lowered = try jsValueLower.printCode([arguments[0]], context) + let kindVar = lowered[0] + let payload1Var = lowered[1] + let payload2Var = lowered[2] + scope.emitPushI32Parameter(kindVar, printer: printer) + scope.emitPushI32Parameter(payload1Var, printer: printer) + scope.emitPushF64Parameter(payload2Var, printer: printer) + return [] + } + ) + case .string: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let value = arguments[0] + let bytesVar = scope.variable("bytes") + let idVar = scope.variable("id") + printer.write("const \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));") + printer.write("const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));") + scope.emitPushI32Parameter("\(bytesVar).length", printer: printer) + scope.emitPushI32Parameter(idVar, printer: printer) + return [] + } + ) + case .bool: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + scope.emitPushI32Parameter("\(arguments[0]) ? 1 : 0", printer: printer) + return [] + } + ) + case .int, .uint: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + scope.emitPushI32Parameter("(\(arguments[0]) | 0)", printer: printer) + return [] + } + ) + case .float: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + scope.emitPushF32Parameter("Math.fround(\(arguments[0]))", printer: printer) + return [] + } + ) + case .double: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + scope.emitPushF64Parameter("\(arguments[0])", printer: printer) + return [] + } + ) + case .swiftStruct(let fullName): + let structBase = fullName.components(separatedBy: ".").last ?? fullName + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) + let value = arguments[0] + let cleanupVar = scope.variable("structCleanup") + printer.write( + "const { cleanup: \(cleanupVar) } = \(JSGlueVariableScope.reservedStructHelpers).\(structBase).lower(\(value));" + ) + cleanup.write("if (\(cleanupVar)) { \(cleanupVar)(); }") + return [] + } + ) + case .caseEnum: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + scope.emitPushI32Parameter("(\(arguments[0]) | 0)", printer: printer) + return [] + } + ) + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let value = arguments[0] + let bytesVar = scope.variable("bytes") + let idVar = scope.variable("id") + printer.write( + "const \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));" + ) + printer.write( + "const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));" + ) + scope.emitPushI32Parameter("\(bytesVar).length", printer: printer) + scope.emitPushI32Parameter(idVar, printer: printer) + return [] + } + ) + case .float: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + scope.emitPushF32Parameter("Math.fround(\(arguments[0]))", printer: printer) + return [] + } + ) + case .double: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + scope.emitPushF64Parameter("\(arguments[0])", printer: printer) + return [] + } + ) + default: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + scope.emitPushI32Parameter("(\(arguments[0]) | 0)", printer: printer) + return [] + } + ) + } + case .associatedValueEnum(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) + let value = arguments[0] + let caseIdVar = scope.variable("caseId") + let cleanupVar = scope.variable("enumCleanup") + printer.write( + "const { caseId: \(caseIdVar), cleanup: \(cleanupVar) } = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(value));" + ) + scope.emitPushI32Parameter(caseIdVar, printer: printer) + cleanup.write("if (\(cleanupVar)) { \(cleanupVar)(); }") + return [] + } + ) + case .swiftHeapObject: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + scope.emitPushPointerParameter("\(arguments[0]).pointer", printer: printer) + return [] + } + ) + case .jsObject: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let value = arguments[0] + let idVar = scope.variable("objId") + printer.write("const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + scope.emitPushI32Parameter(idVar, printer: printer) + return [] + } + ) + case .array(let innerElementType): + return try arrayLower(elementType: innerElementType) + case .dictionary(let valueType): + return try dictionaryLower(valueType: valueType) + case .nullable(let wrappedType, let kind): + return try optionalElementLowerFragment( + wrappedType: wrappedType, + kind: kind + ) + case .swiftProtocol: + // Same as jsObject but no cleanup — Swift's AnyProtocol wrapper releases via deinit + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let value = arguments[0] + let idVar = scope.variable("objId") + printer.write("const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + scope.emitPushI32Parameter(idVar, printer: printer) + return [] + } + ) + case .unsafePointer: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + scope.emitPushPointerParameter("(\(arguments[0]) | 0)", printer: printer) + return [] + } + ) + case .void, .closure, .namespaceEnum: + throw BridgeJSLinkError(message: "Unsupported array element type for lowering: \(elementType)") + } + } + + private static func optionalElementRaiseFragment( + wrappedType: BridgeType, + kind: JSOptionalKind + ) throws -> IntrinsicJSFragment { + let absenceLiteral = kind.absenceLiteral + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let isSomeVar = scope.variable("isSome") + let resultVar = scope.variable("optValue") + + printer.write("const \(isSomeVar) = \(scope.popI32());") + printer.write("let \(resultVar);") + printer.write("if (\(isSomeVar) === 0) {") + printer.indent { + printer.write("\(resultVar) = \(absenceLiteral);") + } + printer.write("} else {") + try printer.indent { + let innerFragment = try stackLiftFragment(elementType: wrappedType) + let innerResults = try innerFragment.printCode([], context) + if let innerResult = innerResults.first { + printer.write("\(resultVar) = \(innerResult);") + } else { + printer.write("\(resultVar) = undefined;") + } + } + printer.write("}") + + return [resultVar] + } + ) + } + + private static func optionalElementLowerFragment( + wrappedType: BridgeType, + kind: JSOptionalKind + ) throws -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let value = arguments[0] + let isSomeVar = scope.variable("isSome") + + let presenceExpr = kind.presenceCheck(value: value) + printer.write("const \(isSomeVar) = \(presenceExpr) ? 1 : 0;") + // Cleanup is written inside the if block so retained id is in scope + let localCleanupWriter = CodeFragmentPrinter() + printer.write("if (\(isSomeVar)) {") + try printer.indent { + let innerFragment = try stackLowerFragment(elementType: wrappedType) + let _ = try innerFragment.printCode( + [value], + context.with(\.cleanupCode, localCleanupWriter) + ) + let localCleanupLines = localCleanupWriter.lines.filter { + !$0.trimmingCharacters(in: .whitespaces).isEmpty + } + if !localCleanupLines.isEmpty { + let localCleanupCode = localCleanupLines.joined(separator: " ") + printer.write("arrayCleanups.push(() => { \(localCleanupCode) });") + } + } + printer.write("} else {") + printer.indent { + // Push placeholders so Swift can unconditionally pop value slots + switch wrappedType { + case .float: + scope.emitPushF32Parameter("0.0", printer: printer) + case .double: + scope.emitPushF64Parameter("0.0", printer: printer) + case .swiftStruct: + // No placeholder — Swift only pops struct fields when isSome=1 + break + case .string, .rawValueEnum(_, .string): + scope.emitPushI32Parameter("0", printer: printer) + scope.emitPushI32Parameter("0", printer: printer) + case .swiftHeapObject: + scope.emitPushPointerParameter("0", printer: printer) + default: + scope.emitPushI32Parameter("0", printer: printer) + } + } + printer.write("}") + scope.emitPushI32Parameter(isSomeVar, printer: printer) + + return [] + } + ) + } + + static func structHelper(structDefinition: ExportedStruct, allStructs: [ExportedStruct]) -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["structName"], + printCode: { arguments, context in + let printer = context.printer + let structName = arguments[0] + let capturedStructDef = structDefinition + let capturedAllStructs = allStructs + + printer.write("const __bjs_create\(structName)Helpers = () => {") + printer.indent() + printer.write( + "return () => ({" + ) + printer.indent() + + printer.write("lower: (value) => {") + try printer.indent { + try generateStructLowerCode( + structDef: capturedStructDef, + allStructs: capturedAllStructs, + context: context + ) + } + printer.write("},") + + printer.write( + "lift: () => {" + ) + try printer.indent { + try generateStructLiftCode( + structDef: capturedStructDef, + allStructs: capturedAllStructs, + context: context, + attachMethods: true + ) + } + printer.write("}") + printer.unindent() + printer.write("});") + printer.unindent() + printer.write("};") + + return [] + } + ) + } + + private static func findStruct(name: String, structs: [ExportedStruct]) -> ExportedStruct? { + return structs.first(where: { $0.swiftCallName == name || $0.name == name }) + } + + private static func generateStructLowerCode( + structDef: ExportedStruct, + allStructs: [ExportedStruct], + context: IntrinsicJSFragment.PrintCodeContext + ) throws { + let (scope, printer) = (context.scope, context.printer) + let lowerPrinter = CodeFragmentPrinter() + let lowerScope = scope.makeChildScope() + let lowerCleanup = CodeFragmentPrinter() + lowerCleanup.indent() + + let instanceProps = structDef.properties.filter { !$0.isStatic } + for property in instanceProps { + let fragment = try structFieldLowerFragment(field: property, allStructs: allStructs) + let fieldValue = "value.\(property.name)" + _ = try fragment.printCode( + [fieldValue], + context.with(\.scope, lowerScope).with(\.printer, lowerPrinter).with(\.cleanupCode, lowerCleanup) + ) + } + + for line in lowerPrinter.lines { + printer.write(line) + } + + if !lowerCleanup.lines.isEmpty { + printer.write("const cleanup = () => {") + printer.write(contentsOf: lowerCleanup) + printer.write("};") + printer.write("return { cleanup };") + } else { + printer.write("return { cleanup: undefined };") + } + } + + private static func generateStructLiftCode( + structDef: ExportedStruct, + allStructs: [ExportedStruct], + context: IntrinsicJSFragment.PrintCodeContext, + attachMethods: Bool = false + ) throws { + let (scope, printer) = (context.scope, context.printer) + let liftScope = context.scope.makeChildScope() + + var fieldExpressions: [(name: String, expression: String)] = [] + + let instanceProps = structDef.properties.filter { !$0.isStatic } + for property in instanceProps.reversed() { + let fragment = try structFieldLiftFragment(field: property, allStructs: allStructs) + let results = try fragment.printCode([], context) + + if let resultExpr = results.first { + fieldExpressions.append((property.name, resultExpr)) + } else { + fieldExpressions.append((property.name, "undefined")) + } + } + + // Construct struct object with fields in original order + let reconstructedFields = instanceProps.map { property in + let expr = fieldExpressions.first(where: { $0.name == property.name })?.expression ?? "undefined" + return "\(property.name): \(expr)" + } + + if attachMethods && !structDef.methods.filter({ !$0.effects.isStatic }).isEmpty { + let instanceVar = liftScope.variable("instance") + printer.write("const \(instanceVar) = { \(reconstructedFields.joined(separator: ", ")) };") + + // Attach instance methods to the struct instance + for method in structDef.methods where !method.effects.isStatic { + let paramList = DefaultValueUtils.formatParameterList(method.parameters) + printer.write( + "\(instanceVar).\(method.name) = function(\(paramList)) {" + ) + try printer.indent { + let methodScope = scope.makeChildScope() + let methodCleanup = CodeFragmentPrinter() + + let structCleanupVar = methodScope.variable("structCleanup") + printer.write( + "const { cleanup: \(structCleanupVar) } = \(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lower(this);" + ) + + var paramForwardings: [String] = [] + for param in method.parameters { + let fragment = try IntrinsicJSFragment.lowerParameter(type: param.type) + let loweredValues = try fragment.printCode([param.name], context) + paramForwardings.append(contentsOf: loweredValues) + } + + let callExpr = "instance.exports.\(method.abiName)(\(paramForwardings.joined(separator: ", ")))" + if method.returnType == .void { + printer.write("\(callExpr);") + } else { + printer.write("const ret = \(callExpr);") + } + + // Cleanup + printer.write("if (\(structCleanupVar)) { \(structCleanupVar)(); }") + printer.write(contentsOf: methodCleanup) + + // Lift return value if needed + if method.returnType != .void { + let liftFragment = try IntrinsicJSFragment.liftReturn(type: method.returnType) + let liftArgs = liftFragment.parameters.isEmpty ? [] : ["ret"] + let lifted = try liftFragment.printCode(liftArgs, context) + if let liftedValue = lifted.first { + printer.write("return \(liftedValue);") + } + } + } + printer.write("}.bind(\(instanceVar));") + } + + printer.write("return \(instanceVar);") + } else { + printer.write("return { \(reconstructedFields.joined(separator: ", ")) };") + } + } + + private static func structFieldLowerFragment( + field: ExportedProperty, + allStructs: [ExportedStruct] + ) throws -> IntrinsicJSFragment { + switch field.type { + case .jsValue: + preconditionFailure("Struct field of JSValue is not supported yet") + case .jsObject: + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let value = arguments[0] + let idVar = scope.variable("id") + printer.write("let \(idVar);") + printer.write("if (\(value) != null) {") + printer.indent { + printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + } + printer.write("} else {") + printer.indent { + printer.write("\(idVar) = undefined;") + } + printer.write("}") + scope.emitPushI32Parameter("\(idVar) !== undefined ? \(idVar) : 0", printer: printer) + return [idVar] + } + ) + case .nullable(let wrappedType, let kind): + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer, cleanup) = (context.scope, context.printer, context.cleanupCode) + let value = arguments[0] + let isSomeVar = scope.variable("isSome") + printer.write("const \(isSomeVar) = \(kind.presenceCheck(value: value));") + + if case .caseEnum = wrappedType { + printer.write("if (\(isSomeVar)) {") + printer.indent { + scope.emitPushI32Parameter("\(value) | 0", printer: printer) + } + printer.write("} else {") + printer.indent { + scope.emitPushI32Parameter("0", printer: printer) + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + return [] + } else if case .rawValueEnum(_, let rawType) = wrappedType { + switch rawType { + case .string: + let idVar = scope.variable("id") + printer.write("let \(idVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + let bytesVar = scope.variable("bytes") + printer.write( + "const \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));" + ) + printer.write( + "\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));" + ) + scope.emitPushI32Parameter("\(bytesVar).length", printer: printer) + scope.emitPushI32Parameter(idVar, printer: printer) + } + printer.write("} else {") + printer.indent { + scope.emitPushI32Parameter("0", printer: printer) + scope.emitPushI32Parameter("0", printer: printer) + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + return [idVar] + case .float: + printer.write("if (\(isSomeVar)) {") + printer.indent { + scope.emitPushF32Parameter("Math.fround(\(value))", printer: printer) + } + printer.write("} else {") + printer.indent { + scope.emitPushF32Parameter("0.0", printer: printer) + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + return [] + case .double: + printer.write("if (\(isSomeVar)) {") + printer.indent { + scope.emitPushF64Parameter("\(value)", printer: printer) + } + printer.write("} else {") + printer.indent { + scope.emitPushF64Parameter("0.0", printer: printer) + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + return [] + default: + printer.write("if (\(isSomeVar)) {") + printer.indent { + scope.emitPushI32Parameter("\(value) | 0", printer: printer) + } + printer.write("} else {") + printer.indent { + scope.emitPushI32Parameter("0", printer: printer) + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + return [] + } + } else if case .swiftHeapObject = wrappedType { + let ptrVar = scope.variable("ptr") + printer.write("let \(ptrVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + printer.write("\(ptrVar) = \(value).pointer;") + scope.emitPushPointerParameter("\(ptrVar)", printer: printer) + } + printer.write("} else {") + printer.indent { + scope.emitPushPointerParameter("0", printer: printer) + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + return [] + } else if case .swiftStruct(let structName) = wrappedType { + let nestedCleanupVar = scope.variable("nestedCleanup") + printer.write("let \(nestedCleanupVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + let structResultVar = scope.variable("structResult") + printer.write( + "const \(structResultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(structName).lower(\(value));" + ) + printer.write("\(nestedCleanupVar) = \(structResultVar).cleanup;") + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + cleanup.write("if (\(nestedCleanupVar)) { \(nestedCleanupVar)(); }") + return [] + } else if case .string = wrappedType { + let idVar = scope.variable("id") + printer.write("let \(idVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + let bytesVar = scope.variable("bytes") + printer.write( + "const \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));" + ) + printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));") + scope.emitPushI32Parameter("\(bytesVar).length", printer: printer) + scope.emitPushI32Parameter(idVar, printer: printer) + } + printer.write("} else {") + printer.indent { + scope.emitPushI32Parameter("0", printer: printer) + scope.emitPushI32Parameter("0", printer: printer) + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + return [idVar] + } else if case .jsObject = wrappedType { + let idVar = scope.variable("id") + printer.write("let \(idVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));") + scope.emitPushI32Parameter(idVar, printer: printer) + } + printer.write("} else {") + printer.indent { + printer.write("\(idVar) = undefined;") + scope.emitPushI32Parameter("0", printer: printer) + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + return [idVar] + } else { + switch wrappedType { + case .int, .uint: + pushOptionalPrimitive( + value: value, + isSomeVar: isSomeVar, + stack: .i32Stack, + convert: "| 0", + zeroValue: "0", + printer: printer, + scope: scope + ) + case .bool: + pushOptionalPrimitive( + value: value, + isSomeVar: isSomeVar, + stack: .i32Stack, + convert: "? 1 : 0", + zeroValue: "0", + printer: printer, + scope: scope + ) + case .float: + pushOptionalPrimitive( + value: value, + isSomeVar: isSomeVar, + stack: .f32Stack, + convert: "Math.fround", + zeroValue: "0.0", + printer: printer, + scope: scope + ) + case .double: + pushOptionalPrimitive( + value: value, + isSomeVar: isSomeVar, + stack: .f64Stack, + convert: nil, + zeroValue: "0.0", + printer: printer, + scope: scope + ) + case .associatedValueEnum(let enumName): + let base = enumName.components(separatedBy: ".").last ?? enumName + let caseIdVar = scope.variable("enumCaseId") + let enumCleanupVar = scope.variable("enumCleanup") + printer.write("let \(caseIdVar), \(enumCleanupVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + let enumResultVar = scope.variable("enumResult") + printer.write( + "const \(enumResultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lower(\(value));" + ) + printer.write("\(caseIdVar) = \(enumResultVar).caseId;") + printer.write("\(enumCleanupVar) = \(enumResultVar).cleanup;") + scope.emitPushI32Parameter(caseIdVar, printer: printer) + } + printer.write("} else {") + printer.indent { + scope.emitPushI32Parameter("0", printer: printer) + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + cleanup.write("if (\(enumCleanupVar)) { \(enumCleanupVar)(); }") + default: + let wrappedFragment = try structFieldLowerFragment( + field: ExportedProperty( + name: field.name, + type: wrappedType, + isReadonly: true, + isStatic: false + ), + allStructs: allStructs + ) + let guardedPrinter = CodeFragmentPrinter() + let guardedCleanup = CodeFragmentPrinter() + _ = try wrappedFragment.printCode( + [value], + context.with(\.printer, guardedPrinter).with(\.cleanupCode, guardedCleanup) + ) + var loweredLines = guardedPrinter.lines + var hoistedCleanupVar: String? + if let first = loweredLines.first { + let trimmed = first.trimmingCharacters(in: .whitespaces) + if trimmed.hasPrefix("const "), + let namePart = trimmed.split(separator: " ").dropFirst().first, + trimmed.contains("= []") + { + hoistedCleanupVar = String(namePart) + loweredLines[0] = "\(hoistedCleanupVar!) = [];" + } + } + if let hoistedName = hoistedCleanupVar { + printer.write("let \(hoistedName);") + } + printer.write("if (\(isSomeVar)) {") + printer.indent { + for line in loweredLines { + printer.write(line) + } + if !guardedCleanup.lines.isEmpty { + cleanup.write("if (\(isSomeVar)) {") + cleanup.indent { + cleanup.write(contentsOf: guardedCleanup) + } + cleanup.write("}") + } + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + } + return [] + } + } + ) + case .swiftStruct(let nestedName): + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let value = arguments[0] + let structResultVar = scope.variable("structResult") + printer.write( + "const \(structResultVar) = \(JSGlueVariableScope.reservedStructHelpers).\(nestedName).lower(\(value));" + ) + context.cleanupCode.write("if (\(structResultVar).cleanup) { \(structResultVar).cleanup(); }") + return [] + } + ) + case .void, .swiftProtocol, .namespaceEnum, .closure: + // These types should not appear as struct fields - return error fragment + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, context in + context.printer.write( + "throw new Error(\"Unsupported struct field type for lowering: \(field.type)\");" + ) + return [] + } + ) + default: + return try stackLowerFragment(elementType: field.type) + } + } + + /// Helper to push optional primitive values to stack-based parameters + private static func pushOptionalPrimitive( + value: String, + isSomeVar: String, + stack: StackType, + convert: String?, + zeroValue: String, + printer: CodeFragmentPrinter, + scope: JSGlueVariableScope + ) { + let stackName: String + switch stack { + case .i32Stack: stackName = JSGlueVariableScope.reservedI32Stack + case .f32Stack: stackName = JSGlueVariableScope.reservedF32Stack + case .f64Stack: stackName = JSGlueVariableScope.reservedF64Stack + } + + printer.write("if (\(isSomeVar)) {") + printer.indent { + let converted: String + if let convert = convert { + if convert.starts(with: "Math.") { + converted = "\(convert)(\(value))" + } else { + converted = "\(value) \(convert)" + } + } else { + converted = value + } + printer.write("\(stackName).push(\(converted));") + } + printer.write("} else {") + printer.indent { + printer.write("\(stackName).push(\(zeroValue));") + } + printer.write("}") + scope.emitPushI32Parameter("\(isSomeVar) ? 1 : 0", printer: printer) + } + + private enum StackType { + case i32Stack + case f32Stack + case f64Stack + } + + private static func structFieldLiftFragment( + field: ExportedProperty, + allStructs: [ExportedStruct] + ) throws -> IntrinsicJSFragment { + switch field.type { + case .jsValue: + preconditionFailure("Struct field of JSValue is not supported yet") + case .nullable(let wrappedType, let kind): + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let isSomeVar = scope.variable("isSome") + let optVar = scope.variable("optional") + printer.write("const \(isSomeVar) = \(scope.popI32());") + printer.write("let \(optVar);") + printer.write("if (\(isSomeVar)) {") + try printer.indent { + // Special handling for associated value enum - in struct fields, case ID is pushed to i32Stack + if case .associatedValueEnum(let enumName) = wrappedType { + let base = enumName.components(separatedBy: ".").last ?? enumName + let caseIdVar = scope.variable("enumCaseId") + printer.write("const \(caseIdVar) = \(scope.popI32());") + printer.write( + "\(optVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(caseIdVar), );" + ) + } else { + let wrappedFragment = try structFieldLiftFragment( + field: ExportedProperty( + name: field.name, + type: wrappedType, + isReadonly: true, + isStatic: false + ), + allStructs: allStructs + ) + let wrappedResults = try wrappedFragment.printCode([], context) + if let wrappedResult = wrappedResults.first { + printer.write("\(optVar) = \(wrappedResult);") + } else { + printer.write("\(optVar) = undefined;") + } + } + } + printer.write("} else {") + printer.indent { + printer.write("\(optVar) = \(kind.absenceLiteral);") + } + printer.write("}") + return [optVar] + } + ) + case .swiftStruct(let nestedName): + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let structVar = scope.variable("struct") + printer.write( + "const \(structVar) = \(JSGlueVariableScope.reservedStructHelpers).\(nestedName).lift();" + ) + return [structVar] + } + ) + case .jsObject: + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let objectIdVar = scope.variable("objectId") + let varName = scope.variable("value") + printer.write("const \(objectIdVar) = \(scope.popI32());") + printer.write("let \(varName);") + printer.write("if (\(objectIdVar) !== 0) {") + printer.indent { + printer.write( + "\(varName) = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(objectIdVar));" + ) + printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(objectIdVar));") + } + printer.write("} else {") + printer.indent { + printer.write("\(varName) = null;") + } + printer.write("}") + return [varName] + } + ) + case .void, .swiftProtocol, .namespaceEnum, .closure: + // These types should not appear as struct fields + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, context in + context.printer.write("throw new Error(\"Unsupported struct field type: \(field.type)\");") + return [] + } + ) + default: + return try stackLiftFragment(elementType: field.type) + } + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSIntrinsicRegistry.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSIntrinsicRegistry.swift new file mode 100644 index 000000000..c3e77d83f --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSIntrinsicRegistry.swift @@ -0,0 +1,37 @@ +#if canImport(BridgeJSUtilities) +import BridgeJSUtilities +#endif + +/// Registry for JS helper intrinsics used during code generation. +final class JSIntrinsicRegistry { + private var entries: [String: [String]] = [:] + + var isEmpty: Bool { + entries.isEmpty + } + + func register(name: String, build: (CodeFragmentPrinter) throws -> Void) rethrows { + guard entries[name] == nil else { return } + let printer = CodeFragmentPrinter() + try build(printer) + entries[name] = printer.lines + } + + func reset() { + entries.removeAll() + } + + func emitLines() -> [String] { + var emitted: [String] = [] + for key in entries.keys.sorted() { + if let lines = entries[key] { + emitted.append(contentsOf: lines) + emitted.append("") + } + } + if emitted.last == "" { + emitted.removeLast() + } + return emitted + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSMacros/BridgeJSMacrosPlugin.swift b/Plugins/BridgeJS/Sources/BridgeJSMacros/BridgeJSMacrosPlugin.swift new file mode 100644 index 000000000..9a45fa0f0 --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSMacros/BridgeJSMacrosPlugin.swift @@ -0,0 +1,12 @@ +import SwiftCompilerPlugin +import SwiftSyntaxMacros + +@main +struct BridgeJSMacrosPlugin: CompilerPlugin { + var providingMacros: [Macro.Type] = [ + JSFunctionMacro.self, + JSGetterMacro.self, + JSSetterMacro.self, + JSClassMacro.self, + ] +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSMacros/JSClassMacro.swift b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSClassMacro.swift new file mode 100644 index 000000000..c44655c7e --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSClassMacro.swift @@ -0,0 +1,164 @@ +import SwiftSyntax +import SwiftSyntaxBuilder +import SwiftSyntaxMacros +import SwiftDiagnostics + +public enum JSClassMacro {} + +extension JSClassMacro: MemberMacro { + public static func expansion( + of node: AttributeSyntax, + providingMembersOf declaration: some DeclGroupSyntax, + conformingTo protocols: [TypeSyntax], + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + guard declaration.is(StructDeclSyntax.self) else { + var fixIts: [FixIt] = [] + let note = Note( + node: Syntax(declaration), + message: JSMacroNoteMessage( + message: "Use @JSClass on a struct wrapper to synthesize jsObject and JS bridging members." + ) + ) + + if let classDecl = declaration.as(ClassDeclSyntax.self) { + let structKeyword = classDecl.classKeyword.with(\.tokenKind, .keyword(.struct)) + fixIts.append( + FixIt( + message: JSMacroFixItMessage(message: "Change 'class' to 'struct'"), + changes: [ + .replace( + oldNode: Syntax(classDecl.classKeyword), + newNode: Syntax(structKeyword) + ) + ] + ) + ) + } + context.diagnose( + Diagnostic( + node: Syntax(declaration), + message: JSMacroMessage.unsupportedJSClassDeclaration, + notes: [note], + fixIts: fixIts + ) + ) + return [] + } + + var members: [DeclSyntax] = [] + guard let structDecl = declaration.as(StructDeclSyntax.self) else { return members } + + if let accessLevel = accessLevel(from: structDecl.modifiers), + accessLevel == .private || accessLevel == .fileprivate + { + context.diagnose( + Diagnostic( + node: Syntax(structDecl), + message: JSMacroMessage.jsClassRequiresAtLeastInternal + ) + ) + return [] + } + + let memberAccessModifier = synthesizedMemberAccessModifier(for: declaration).map { "\($0) " } ?? "" + + let existingMembers = declaration.memberBlock.members + let hasJSObjectProperty = existingMembers.contains { member in + guard let variable = member.decl.as(VariableDeclSyntax.self) else { return false } + return variable.bindings.contains { binding in + binding.pattern.as(IdentifierPatternSyntax.self)?.identifier.text == "jsObject" + } + } + + if !hasJSObjectProperty { + members.append(DeclSyntax("\(raw: memberAccessModifier)let jsObject: JSObject")) + } + + let hasUnsafelyWrappingInit = existingMembers.contains { member in + guard let initializer = member.decl.as(InitializerDeclSyntax.self) else { return false } + let parameters = initializer.signature.parameterClause.parameters + guard let firstParam = parameters.first else { return false } + let externalName = firstParam.firstName.text + let internalName = firstParam.secondName?.text + return externalName == "unsafelyWrapping" && internalName == "jsObject" + } + + if !hasUnsafelyWrappingInit { + members.append( + DeclSyntax( + """ + \(raw: memberAccessModifier)init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + """ + ) + ) + } + + return members + } +} + +extension JSClassMacro: ExtensionMacro { + public static func expansion( + of node: AttributeSyntax, + attachedTo declaration: some DeclGroupSyntax, + providingExtensionsOf type: some TypeSyntaxProtocol, + conformingTo protocols: [TypeSyntax], + in context: some MacroExpansionContext + ) throws -> [ExtensionDeclSyntax] { + guard let structDecl = declaration.as(StructDeclSyntax.self) else { return [] } + guard !protocols.isEmpty else { return [] } + if let accessLevel = accessLevel(from: structDecl.modifiers), + accessLevel == .private || accessLevel == .fileprivate + { + 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) {}") + ] + } + + private static func synthesizedMemberAccessModifier(for declaration: some DeclGroupSyntax) -> String? { + guard let structDecl = declaration.as(StructDeclSyntax.self) else { return nil } + switch accessLevel(from: structDecl.modifiers) { + case .public: return "public" + case .package: return "package" + case .internal: return "internal" + case .fileprivate, .private, .none: return nil + } + } + + private enum AccessLevel { + case `public` + case package + case `internal` + case `fileprivate` + case `private` + } + + private static func accessLevel(from modifiers: DeclModifierListSyntax?) -> AccessLevel? { + guard let modifiers else { return nil } + for modifier in modifiers { + switch modifier.name.tokenKind { + case .keyword(.public): return .public + case .keyword(.package): return .package + case .keyword(.internal): return .internal + case .keyword(.fileprivate): return .fileprivate + case .keyword(.private): return .private + default: continue + } + } + return nil + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSMacros/JSFunctionMacro.swift b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSFunctionMacro.swift new file mode 100644 index 000000000..0fff3546a --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSFunctionMacro.swift @@ -0,0 +1,141 @@ +import SwiftSyntax +import SwiftSyntaxBuilder +import SwiftSyntaxMacros +import SwiftDiagnostics + +public enum JSFunctionMacro {} + +extension JSFunctionMacro: BodyMacro { + public static func expansion( + of node: AttributeSyntax, + providingBodyFor declaration: some DeclSyntaxProtocol & WithOptionalCodeBlockSyntax, + in context: some MacroExpansionContext + ) throws -> [CodeBlockItemSyntax] { + if let functionDecl = declaration.as(FunctionDeclSyntax.self) { + let enclosingTypeName = JSMacroHelper.enclosingTypeName(from: context) + let isStatic = JSMacroHelper.isStatic(functionDecl.modifiers) + let isTopLevel = enclosingTypeName == nil + let isInstanceMember = !isTopLevel && !isStatic + if !isTopLevel { + JSMacroHelper.diagnoseMissingJSClass(node: node, for: "JSFunction", in: context) + } + + JSMacroHelper.diagnoseThrowsRequiresJSException( + signature: functionDecl.signature, + on: Syntax(functionDecl), + in: context + ) + + // Strip backticks from function name (e.g., "`prefix`" -> "prefix") + // Backticks are only needed for Swift identifiers, not function names + let name = JSMacroHelper.stripBackticks(functionDecl.name.text) + let glueName = JSMacroHelper.glueName(baseName: name, enclosingTypeName: enclosingTypeName) + + var arguments: [String] = [] + if isInstanceMember { + arguments.append("self.jsObject") + } + arguments.append( + contentsOf: JSMacroHelper.parameterNames(functionDecl.signature.parameterClause.parameters) + ) + + let argsJoined = arguments.joined(separator: ", ") + let call = "\(glueName)(\(argsJoined))" + + let effects = functionDecl.signature.effectSpecifiers + let isAsync = effects?.asyncSpecifier != nil + let prefix = JSMacroHelper.tryAwaitPrefix(isAsync: isAsync, isThrows: true) + + let isVoid = JSMacroHelper.isVoidReturn(functionDecl.signature.returnClause?.type) + let line = isVoid ? "\(prefix)\(call)" : "return \(prefix)\(call)" + return [CodeBlockItemSyntax(stringLiteral: line)] + } + + if let initializerDecl = declaration.as(InitializerDeclSyntax.self) { + guard let enclosingTypeName = JSMacroHelper.enclosingTypeName(from: context) else { + context.diagnose( + Diagnostic( + node: Syntax(declaration), + message: JSMacroMessage.unsupportedDeclaration, + notes: [ + Note( + node: Syntax(declaration), + message: JSMacroNoteMessage( + message: "Move this initializer inside a JS wrapper type annotated with @JSClass." + ) + ) + ] + ) + ) + return [CodeBlockItemSyntax(stringLiteral: "fatalError(\"@JSFunction init must be inside a type\")")] + } + + JSMacroHelper.diagnoseMissingJSClass(node: node, for: "JSFunction", in: context) + JSMacroHelper.diagnoseThrowsRequiresJSException( + signature: initializerDecl.signature, + on: Syntax(initializerDecl), + in: context + ) + + let glueName = JSMacroHelper.glueName(baseName: "init", enclosingTypeName: enclosingTypeName) + let parameters = initializerDecl.signature.parameterClause.parameters + let arguments = JSMacroHelper.parameterNames(parameters) + let call = "\(glueName)(\(arguments.joined(separator: ", ")))" + + let effects = initializerDecl.signature.effectSpecifiers + let isAsync = effects?.asyncSpecifier != nil + let prefix = JSMacroHelper.tryAwaitPrefix(isAsync: isAsync, isThrows: true) + + return [ + CodeBlockItemSyntax(stringLiteral: "let jsObject = \(prefix)\(call)"), + CodeBlockItemSyntax(stringLiteral: "self.init(unsafelyWrapping: jsObject)"), + ] + } + + context.diagnose( + Diagnostic( + node: Syntax(declaration), + message: JSMacroMessage.unsupportedDeclaration, + notes: [ + Note( + node: Syntax(declaration), + message: JSMacroNoteMessage( + message: "Apply @JSFunction to a function or initializer on your @JSClass wrapper type." + ) + ) + ] + ) + ) + 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, + notes: [ + Note( + node: Syntax(declaration), + message: JSMacroNoteMessage( + message: + "Place @JSFunction on a function or initializer; use @JSGetter/@JSSetter for properties." + ) + ) + ] + ) + ) + return [] + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSMacros/JSGetterMacro.swift b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSGetterMacro.swift new file mode 100644 index 000000000..a3b9435ea --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSGetterMacro.swift @@ -0,0 +1,109 @@ +import SwiftSyntax +import SwiftSyntaxBuilder +import SwiftSyntaxMacros +import SwiftDiagnostics + +public enum JSGetterMacro {} + +extension JSGetterMacro: AccessorMacro { + public static func expansion( + of node: AttributeSyntax, + providingAccessorsOf declaration: some DeclSyntaxProtocol, + in context: some MacroExpansionContext + ) throws -> [AccessorDeclSyntax] { + guard let variableDecl = declaration.as(VariableDeclSyntax.self), + let binding = variableDecl.bindings.first, + let identifier = binding.pattern.as(IdentifierPatternSyntax.self) + else { + context.diagnose( + Diagnostic( + node: Syntax(declaration), + message: JSMacroMessage.unsupportedVariable, + notes: [ + Note( + node: Syntax(declaration), + message: JSMacroNoteMessage( + message: "@JSGetter must be attached to a single stored or computed property." + ) + ) + ] + ) + ) + return [] + } + + let enclosingTypeName = JSMacroHelper.enclosingTypeName(from: context) + let isStatic = JSMacroHelper.isStatic(variableDecl.modifiers) + let isTopLevel = enclosingTypeName == nil + let isInstanceMember = !isTopLevel && !isStatic + if !isTopLevel { + JSMacroHelper.diagnoseMissingJSClass(node: node, for: "JSGetter", in: context) + } + + // Strip backticks from property name (e.g., "`prefix`" -> "prefix") + // Backticks are only needed for Swift identifiers, not function names + let propertyName = JSMacroHelper.stripBackticks(identifier.identifier.text) + let getterName = JSMacroHelper.glueName( + baseName: propertyName, + enclosingTypeName: enclosingTypeName, + operation: "get" + ) + + var getterArgs: [String] = [] + if isInstanceMember { + getterArgs.append("self.jsObject") + } + let getterCall: CodeBlockItemSyntax = + "return try \(raw: getterName)(\(raw: getterArgs.joined(separator: ", ")))" + + let throwsClause = ThrowsClauseSyntax( + throwsSpecifier: .keyword(.throws), + leftParen: .leftParenToken(), + type: IdentifierTypeSyntax(name: .identifier("JSException")), + rightParen: .rightParenToken() + ) + + return [ + AccessorDeclSyntax( + accessorSpecifier: .keyword(.get), + effectSpecifiers: AccessorEffectSpecifiersSyntax( + asyncSpecifier: nil, + throwsClause: throwsClause + ), + body: CodeBlockSyntax { + getterCall + } + ) + ] + } +} + +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, + notes: [ + Note( + node: Syntax(declaration), + message: JSMacroNoteMessage( + message: "@JSGetter must be attached to a single stored or computed property." + ) + ) + ] + ) + ) + return [] + } + return [] + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSMacros/JSMacroSupport.swift b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSMacroSupport.swift new file mode 100644 index 000000000..224462ddb --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSMacroSupport.swift @@ -0,0 +1,271 @@ +import SwiftSyntax +import SwiftSyntaxBuilder +import SwiftSyntaxMacros +import SwiftDiagnostics + +enum JSMacroMessage: String, DiagnosticMessage { + case unsupportedDeclaration = "@JSFunction can only be applied to functions or initializers." + case unsupportedJSClassDeclaration = "@JSClass can only be applied to structs." + case unsupportedVariable = "@JSGetter can only be applied to single-variable declarations." + case unsupportedSetterDeclaration = "@JSSetter can only be applied to functions." + case invalidSetterName = + "@JSSetter function name must start with 'set' followed by a property name (e.g., 'setFoo')." + case setterRequiresParameter = "@JSSetter function must have at least one parameter." + case setterRequiresThrows = "@JSSetter function must declare throws(JSException)." + case jsFunctionRequiresThrows = "@JSFunction throws must be declared as throws(JSException)." + case requiresJSClass = "JavaScript members must be declared inside a @JSClass struct." + case jsClassRequiresAtLeastInternal = + "@JSClass does not support private/fileprivate access level. Use internal, package, or public." + case jsClassMemberRequiresAtLeastInternal = + "@JSClass requires jsObject and init(unsafelyWrapping:) to be at least internal." + + var message: String { rawValue } + var diagnosticID: MessageID { MessageID(domain: "JavaScriptKitMacros", id: rawValue) } + var severity: DiagnosticSeverity { .error } +} + +struct JSMacroNoteMessage: NoteMessage { + let message: String + var noteID: MessageID { MessageID(domain: "JavaScriptKitMacros", id: message) } +} + +struct JSMacroFixItMessage: FixItMessage { + let message: String + var fixItID: MessageID { MessageID(domain: "JavaScriptKitMacros", id: message) } +} + +enum JSMacroText { + static let jsExceptionPropagation = "@JSFunction must propagate JavaScript errors as JSException." + static let jsSetterExceptionPropagation = "@JSSetter must propagate JavaScript errors as JSException." +} + +enum JSMacroHelper { + static func enclosingTypeName(from context: some MacroExpansionContext) -> String? { + enclosingTypeSyntax(from: context).flatMap(typeName(of:)) + } + + static func enclosingTypeSyntax(from context: some MacroExpansionContext) -> Syntax? { + for syntax in context.lexicalContext { + if syntax.is(ClassDeclSyntax.self) || syntax.is(StructDeclSyntax.self) + || syntax.is(EnumDeclSyntax.self) || syntax.is(ActorDeclSyntax.self) + { + return Syntax(syntax) + } + } + return nil + } + + static func isStatic(_ modifiers: DeclModifierListSyntax?) -> Bool { + guard let modifiers else { return false } + return modifiers.contains { modifier in + modifier.name.tokenKind == .keyword(.static) || modifier.name.tokenKind == .keyword(.class) + } + } + + static func isVoidReturn(_ returnType: TypeSyntax?) -> Bool { + guard let returnType else { return true } + if let identifier = returnType.as(IdentifierTypeSyntax.self), identifier.name.text == "Void" { + return true + } + if let tuple = returnType.as(TupleTypeSyntax.self), tuple.elements.isEmpty { + return true + } + return false + } + + static func glueName(baseName: String, enclosingTypeName: String?) -> String { + if let enclosingTypeName { + return "_$\(enclosingTypeName)_\(baseName)" + } + return "_$\(baseName)" + } + + static func glueName(baseName: String, enclosingTypeName: String?, operation: String) -> String { + if let enclosingTypeName { + return "_$\(enclosingTypeName)_\(baseName)_\(operation)" + } + return "_$\(baseName)_\(operation)" + } + + static func parameterNames(_ parameters: FunctionParameterListSyntax) -> [String] { + parameters.compactMap { param in + let nameToken = param.secondName ?? param.firstName + let nameText = nameToken.text + return nameText == "_" ? nil : nameText + } + } + + static func tryAwaitPrefix(isAsync: Bool, isThrows: Bool) -> String { + switch (isAsync, isThrows) { + case (true, true): + return "try await " + case (true, false): + return "await " + case (false, true): + return "try " + case (false, false): + return "" + } + } + + /// Strips backticks from an identifier name. + /// Swift identifiers with keywords are escaped with backticks (e.g., `` `prefix` ``), + /// but function names should not include backticks. + static func stripBackticks(_ name: String) -> String { + if name.hasPrefix("`") && name.hasSuffix("`") && name.count > 2 { + return String(name.dropFirst().dropLast()) + } + return name + } + + static func capitalizingFirstLetter(_ value: String) -> String { + guard let first = value.first else { return value } + return first.uppercased() + value.dropFirst() + } + + static func hasJSClassAttribute(_ typeSyntax: Syntax) -> Bool { + guard let attributes = attributes(of: typeSyntax) else { return false } + for attribute in attributes.compactMap({ $0.as(AttributeSyntax.self) }) { + let name = attribute.attributeName.trimmedDescription + if name == "JSClass" || name == "@JSClass" { + return true + } + } + return false + } + + static func typeName(of syntax: Syntax) -> String? { + switch syntax.as(SyntaxEnum.self) { + case .structDecl(let decl): return decl.name.text + case .classDecl(let decl): return decl.name.text + case .enumDecl(let decl): return decl.name.text + case .actorDecl(let decl): return decl.name.text + default: return nil + } + } + + private static func attributes(of syntax: Syntax) -> AttributeListSyntax? { + switch syntax.as(SyntaxEnum.self) { + case .structDecl(let decl): return decl.attributes + case .classDecl(let decl): return decl.attributes + case .enumDecl(let decl): return decl.attributes + case .actorDecl(let decl): return decl.attributes + default: return nil + } + } + + static func diagnoseThrowsRequiresJSException( + signature: FunctionSignatureSyntax, + on node: Syntax, + in context: some MacroExpansionContext, + additionalNotes: [Note] = [] + ) { + let throwsClause = signature.effectSpecifiers?.throwsClause + let throwsTypeName = throwsClause?.type?.as(IdentifierTypeSyntax.self)?.name.text + let isJSException = throwsTypeName == "JSException" + let isAllowedGenericError = + throwsClause != nil + && (throwsTypeName == nil || throwsTypeName == "Error" || throwsTypeName == "Swift.Error") + guard !isJSException else { return } + guard !isAllowedGenericError else { return } + + let newThrowsClause = jsExceptionThrowsClause(from: throwsClause) + + let fixIt: FixIt + if let throwsClause = signature.effectSpecifiers?.throwsClause { + fixIt = FixIt( + message: JSMacroFixItMessage(message: "Declare throws(JSException)"), + changes: [.replace(oldNode: Syntax(throwsClause), newNode: Syntax(newThrowsClause))] + ) + } else { + let adjustedParameterClause = signature.parameterClause.with(\.rightParen.trailingTrivia, .spaces(0)) + let newEffects = FunctionEffectSpecifiersSyntax( + asyncSpecifier: signature.effectSpecifiers?.asyncSpecifier, + throwsClause: newThrowsClause + ) + let newSignature = + signature + .with(\.parameterClause, adjustedParameterClause) + .with(\.effectSpecifiers, newEffects) + fixIt = FixIt( + message: JSMacroFixItMessage(message: "Declare throws(JSException)"), + changes: [.replace(oldNode: Syntax(signature), newNode: Syntax(newSignature))] + ) + } + + var notes: [Note] = [ + jsExceptionPropagationNote(on: node) + ] + notes.append(contentsOf: additionalNotes) + + context.diagnose( + Diagnostic( + node: node, + message: JSMacroMessage.jsFunctionRequiresThrows, + notes: notes, + fixIts: [fixIt] + ) + ) + } + + static func diagnoseMissingJSClass( + node: some SyntaxProtocol, + for macroName: String, + in context: some MacroExpansionContext + ) { + guard let typeSyntax = enclosingTypeSyntax(from: context) else { return } + guard !hasJSClassAttribute(typeSyntax) else { return } + context.diagnose(Diagnostic(node: node, message: JSMacroMessage.requiresJSClass)) + } + + static func setterPropertyBase(from parameter: FunctionParameterSyntax?) -> String? { + guard let parameter else { return nil } + let candidateNames = [ + parameter.secondName, + parameter.firstName.tokenKind == .wildcard ? nil : parameter.firstName, + ].compactMap { $0?.text }.filter { $0 != "_" } + if let explicitName = candidateNames.first(where: { name in name != "value" && name != "newValue" }) { + return explicitName + } + if let identifierType = parameter.type.as(IdentifierTypeSyntax.self) { + let typeName = identifierType.name.text + guard let first = typeName.first else { return nil } + return first.lowercased() + typeName.dropFirst() + } + return candidateNames.first + } + + static func suggestedSetterName(rawFunctionName: String, firstParameter: FunctionParameterSyntax?) -> String? { + guard let base = setterPropertyBase(from: firstParameter) else { return nil } + return "set" + capitalizingFirstLetter(base) + } + + /// Build a typed throws(JSException) clause preserving trivia when possible. + static func jsExceptionThrowsClause(from throwsClause: ThrowsClauseSyntax?) -> ThrowsClauseSyntax { + let throwsSpecifier = (throwsClause?.throwsSpecifier ?? .keyword(.throws, leadingTrivia: .space)) + .with(\.trailingTrivia, .spaces(0)) + .with(\.leadingTrivia, throwsClause?.throwsSpecifier.leadingTrivia ?? .space) + let leftParen = throwsClause?.leftParen ?? .leftParenToken() + let rightParen = (throwsClause?.rightParen ?? .rightParenToken()) + .with(\.trailingTrivia, throwsClause?.rightParen?.trailingTrivia ?? .space) + + return ThrowsClauseSyntax( + throwsSpecifier: throwsSpecifier, + leftParen: leftParen, + type: TypeSyntax(IdentifierTypeSyntax(name: .identifier("JSException"))), + rightParen: rightParen + ) + } + + static func jsExceptionPropagationNote( + on node: Syntax, + message: String = JSMacroText.jsExceptionPropagation + ) -> Note { + Note( + node: node, + message: JSMacroNoteMessage( + message: message + ) + ) + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSMacros/JSSetterMacro.swift b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSSetterMacro.swift new file mode 100644 index 000000000..4d32db449 --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSMacros/JSSetterMacro.swift @@ -0,0 +1,251 @@ +import SwiftSyntax +import SwiftSyntaxBuilder +import SwiftSyntaxMacros +import SwiftDiagnostics + +public enum JSSetterMacro {} + +extension JSSetterMacro: BodyMacro { + public static func expansion( + of node: AttributeSyntax, + providingBodyFor declaration: some DeclSyntaxProtocol & WithOptionalCodeBlockSyntax, + in context: some MacroExpansionContext + ) throws -> [CodeBlockItemSyntax] { + guard let functionDecl = declaration.as(FunctionDeclSyntax.self) else { + context.diagnose( + Diagnostic( + node: Syntax(declaration), + message: JSMacroMessage.unsupportedSetterDeclaration, + notes: [ + Note( + node: Syntax(declaration), + message: JSMacroNoteMessage( + message: "@JSSetter can only be used on methods that set a JavaScript property." + ) + ) + ] + ) + ) + return [] + } + + let functionName = functionDecl.name.text + let parameters = functionDecl.signature.parameterClause.parameters + let suggestedSetterName = JSMacroHelper.suggestedSetterName( + rawFunctionName: JSMacroHelper.stripBackticks(functionName), + firstParameter: parameters.first + ) + let renameFixIts: [FixIt] + if let name = suggestedSetterName { + let replacement = functionDecl.name.with(\.tokenKind, .identifier(name)) + .with(\.leadingTrivia, functionDecl.name.leadingTrivia) + .with(\.trailingTrivia, functionDecl.name.trailingTrivia) + renameFixIts = [ + FixIt( + message: JSMacroFixItMessage(message: "Rename setter to '\(name)'"), + changes: [.replace(oldNode: Syntax(functionDecl.name), newNode: Syntax(replacement))] + ) + ] + } else { + renameFixIts = [] + } + let addParameterFixIts: [FixIt] = { + let placeholderParameter = FunctionParameterSyntax( + firstName: .wildcardToken(trailingTrivia: .space), + secondName: .identifier("value"), + colon: .colonToken(trailingTrivia: .space), + type: IdentifierTypeSyntax(name: TokenSyntax(.identifier("<#Type#>"), presence: .present)) + ) + let newClause = FunctionParameterClauseSyntax( + leftParen: .leftParenToken(), + parameters: FunctionParameterListSyntax([placeholderParameter]), + rightParen: .rightParenToken(trailingTrivia: .space) + ) + return [ + FixIt( + message: JSMacroFixItMessage(message: "Add a value parameter to the setter"), + changes: [ + .replace( + oldNode: Syntax(functionDecl.signature.parameterClause), + newNode: Syntax(newClause) + ) + ] + ) + ] + }() + + // Extract property name from setter function name (e.g., "setFoo" -> "foo") + // Strip backticks if present (e.g., "set`prefix`" -> "prefix") + let rawFunctionName = JSMacroHelper.stripBackticks(functionName) + guard rawFunctionName.hasPrefix("set"), rawFunctionName.count > 3 else { + context.diagnose( + Diagnostic( + node: Syntax(declaration), + message: JSMacroMessage.invalidSetterName, + notes: [ + Note( + node: Syntax(functionDecl.name), + message: JSMacroNoteMessage( + message: "Setter names must start with 'set' followed by the property name." + ) + ) + ], + fixIts: renameFixIts + ) + ) + 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, + notes: [ + Note( + node: Syntax(functionDecl.name), + message: JSMacroNoteMessage( + message: "Setter names must include the property after 'set'." + ) + ) + ], + fixIts: renameFixIts + ) + ) + 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") + let baseName = propertyName.prefix(1).lowercased() + propertyName.dropFirst() + + let enclosingTypeName = JSMacroHelper.enclosingTypeName(from: context) + let isStatic = JSMacroHelper.isStatic(functionDecl.modifiers) + let isTopLevel = enclosingTypeName == nil + let isInstanceMember = !isTopLevel && !isStatic + if !isTopLevel { + JSMacroHelper.diagnoseMissingJSClass(node: node, for: "JSSetter", in: context) + } + + let glueName = JSMacroHelper.glueName( + baseName: baseName, + enclosingTypeName: enclosingTypeName, + operation: "set" + ) + + var arguments: [String] = [] + if isInstanceMember { + arguments.append("self.jsObject") + } + + // Get the parameter name(s) - setters typically have one parameter + guard let firstParam = parameters.first else { + context.diagnose( + Diagnostic( + node: Syntax(declaration), + message: JSMacroMessage.setterRequiresParameter, + notes: [ + Note( + node: Syntax(declaration), + message: JSMacroNoteMessage( + message: "@JSSetter needs a parameter for the value being assigned." + ) + ) + ], + fixIts: addParameterFixIts + ) + ) + return [ + CodeBlockItemSyntax( + stringLiteral: "fatalError(\"@JSSetter function must have at least one parameter\")" + ) + ] + } + + let paramName = firstParam.secondName ?? firstParam.firstName + arguments.append(paramName.text) + + // Ensure throws(JSException) is declared to match the generated body. + let existingThrowsClause = functionDecl.signature.effectSpecifiers?.throwsClause + let existingThrowsType = existingThrowsClause?.type + .flatMap { $0.as(IdentifierTypeSyntax.self)?.name.text } + let hasTypedJSException = existingThrowsType == "JSException" + let isAllowedGenericError = + existingThrowsClause != nil + && (existingThrowsType == nil || existingThrowsType == "Error" || existingThrowsType == "Swift.Error") + + if !hasTypedJSException && !isAllowedGenericError { + let throwsClause = JSMacroHelper.jsExceptionThrowsClause( + from: existingThrowsClause + ) + let newEffects = + (functionDecl.signature.effectSpecifiers + ?? FunctionEffectSpecifiersSyntax(asyncSpecifier: nil, throwsClause: nil)) + .with(\.throwsClause, throwsClause) + let newSignature = functionDecl.signature.with(\.effectSpecifiers, newEffects) + let fixIt = FixIt( + message: JSMacroFixItMessage(message: "Declare throws(JSException)"), + changes: [.replace(oldNode: Syntax(functionDecl.signature), newNode: Syntax(newSignature))] + ) + let notes: [Note] = [ + JSMacroHelper.jsExceptionPropagationNote( + on: Syntax(functionDecl), + message: JSMacroText.jsSetterExceptionPropagation + ) + ] + context.diagnose( + Diagnostic( + node: Syntax(functionDecl), + message: JSMacroMessage.setterRequiresThrows, + notes: notes, + fixIts: [fixIt] + ) + ) + } + + let argsJoined = arguments.joined(separator: ", ") + let call = "\(glueName)(\(argsJoined))" + + // Setters should throw JSException, so always use try + 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, + notes: [ + Note( + node: Syntax(declaration), + message: JSMacroNoteMessage( + message: "@JSSetter should be attached to a method that writes a JavaScript property." + ) + ) + ] + ) + ) + return [] + } + return [] + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift index a3c5b4014..ba25b6ff9 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift @@ -1,46 +1,604 @@ // This file is shared between BridgeTool and BridgeJSLink +// MARK: - ABI Name Generation + +/// Utility for generating consistent ABI names across all exported and imported types +public struct ABINameGenerator { + static let prefixComponent = "bjs" + + /// Generates ABI name using standardized namespace + context pattern + public static func generateABIName( + baseName: String, + namespace: [String]? = nil, + staticContext: StaticContext? = nil, + operation: String? = nil, + className: String? = nil + ) -> String { + + let namespacePart: String? + if let namespace = namespace, !namespace.isEmpty { + namespacePart = namespace.joined(separator: "_") + } else { + namespacePart = nil + } + + let contextPart: String? + if let staticContext = staticContext { + switch staticContext { + case .className(let name), .enumName(let name), .structName(let name): + contextPart = name + case .namespaceEnum: + contextPart = namespacePart + } + } else if let className = className { + contextPart = className + } else { + contextPart = namespacePart + } + + var components = [ABINameGenerator.prefixComponent] + if let context = contextPart { + components.append(context) + } + + if staticContext != nil { + components.append("static") + } + + components.append(baseName) + + if let operation = operation { + components.append(operation) + } + + return components.joined(separator: "_") + } + + static func generateImportedABIName( + baseName: String, + context: ImportedTypeSkeleton? = nil, + operation: String? = nil + ) -> String { + return [ABINameGenerator.prefixComponent, context?.name, baseName, operation].compactMap { $0 }.joined( + separator: "_" + ) + } +} + // MARK: - Types -public enum BridgeType: Codable, Equatable { - case int, float, double, string, bool, jsObject(String?), swiftHeapObject(String), void +/// Context for bridge operations that determines which types are valid +public enum BridgeContext: Sendable { + case importTS + case exportSwift +} + +public struct ClosureSignature: Codable, Equatable, Hashable, Sendable { + public let parameters: [BridgeType] + public let returnType: BridgeType + /// Simplified Swift ABI-style mangling with module prefix + // + params + _ + return + // Examples: + // - 4MainSS_Si (Main module, String->Int) + // - 6MyAppSiSi_y (MyApp module, Int,Int->Void) + public let mangleName: String + public let isAsync: Bool + public let isThrows: Bool + public let moduleName: String + + public init( + parameters: [BridgeType], + returnType: BridgeType, + moduleName: String, + isAsync: Bool = false, + isThrows: Bool = false + ) { + self.parameters = parameters + self.returnType = returnType + self.moduleName = moduleName + self.isAsync = isAsync + self.isThrows = isThrows + let paramPart = + parameters.isEmpty + ? "y" + : parameters.map { $0.mangleTypeName }.joined() + let signaturePart = "\(paramPart)_\(returnType.mangleTypeName)" + self.mangleName = "\(moduleName.count)\(moduleName)\(signaturePart)" + } +} + +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 + } +} + +/// JS semantics for optional/nullable types: which value represents "absent". +public enum JSOptionalKind: String, Codable, Equatable, Hashable, Sendable { + case null + case undefined + + /// The JS literal for absence (e.g. in generated glue). + public var absenceLiteral: String { + switch self { + case .null: return "null" + case .undefined: return "undefined" + } + } + + /// JS expression that is true when the value is present. `value` is the variable name. + public func presenceCheck(value: String) -> String { + switch self { + case .null: return "\(value) != null" + case .undefined: return "\(value) !== undefined" + } + } +} + +public enum BridgeType: Codable, Equatable, Hashable, Sendable { + case int, uint, float, double, string, bool, jsObject(String?), jsValue, swiftHeapObject(String), void + case unsafePointer(UnsafePointerType) + indirect case nullable(BridgeType, JSOptionalKind) + indirect case array(BridgeType) + indirect case dictionary(BridgeType) + case caseEnum(String) + case rawValueEnum(String, SwiftEnumRawType) + case associatedValueEnum(String) + case namespaceEnum(String) + case swiftProtocol(String) + case swiftStruct(String) + indirect case closure(ClosureSignature, useJSTypedClosure: Bool) } -public enum WasmCoreType: String, Codable { +public enum WasmCoreType: String, Codable, Sendable { case i32, i64, f32, f64, pointer } -public struct Parameter: Codable { +public enum SwiftEnumRawType: String, CaseIterable, Codable, Sendable { + case string = "String" + case bool = "Bool" + case int = "Int" + case int32 = "Int32" + case int64 = "Int64" + case uint = "UInt" + case uint32 = "UInt32" + case uint64 = "UInt64" + case float = "Float" + case double = "Double" + + public var wasmCoreType: WasmCoreType? { + switch self { + case .string: + return nil + case .bool, .int, .int32, .uint, .uint32: + return .i32 + case .int64, .uint64: + return .i64 + case .float: + return .f32 + case .double: + return .f64 + } + } + + public init?(_ rawTypeString: String?) { + guard let rawTypeString = rawTypeString, + let match = Self.allCases.first(where: { $0.rawValue == rawTypeString }) + else { + return nil + } + self = match + } +} + +/// Represents a struct field with name and default value for default parameter values +public struct DefaultValueField: Codable, Equatable, Sendable { + public let name: String + public let value: DefaultValue + + public init(name: String, value: DefaultValue) { + self.name = name + self.value = value + } +} + +public enum DefaultValue: Codable, Equatable, Sendable { + case string(String) + case int(Int) + case float(Float) + case double(Double) + case bool(Bool) + case null + case enumCase(String, String) // enumName, caseName + case object(String) // className for parameterless constructor + case objectWithArguments(String, [DefaultValue]) // className, constructor argument values + case structLiteral(String, [DefaultValueField]) // structName, field name/value pairs + indirect case array([DefaultValue]) // array literal with element values +} + +public struct Parameter: Codable, Equatable, Sendable { public let label: String? public let name: String public let type: BridgeType + public let defaultValue: DefaultValue? + + public var hasDefault: Bool { + return defaultValue != nil + } - public init(label: String?, name: String, type: BridgeType) { + public init(label: String?, name: String, type: BridgeType, defaultValue: DefaultValue? = nil) { self.label = label self.name = name self.type = type + self.defaultValue = defaultValue + } +} + +// MARK: - BridgeType Visitor + +public protocol BridgeTypeVisitor { + mutating func visitClosure(_ signature: ClosureSignature, useJSTypedClosure: Bool) +} + +public struct BridgeTypeWalker { + public var visitor: Visitor + + public init(visitor: Visitor) { + self.visitor = visitor + } + + public mutating func walk(_ type: BridgeType) { + switch type { + case .closure(let signature, let useJSTypedClosure): + visitor.visitClosure(signature, useJSTypedClosure: useJSTypedClosure) + for paramType in signature.parameters { + walk(paramType) + } + walk(signature.returnType) + case .nullable(let wrapped, _): + walk(wrapped) + case .array(let element): + walk(element) + case .dictionary(let value): + walk(value) + default: + break + } + } + public mutating func walk(_ parameters: [Parameter]) { + for param in parameters { + walk(param.type) + } + } + public mutating func walk(_ function: ExportedFunction) { + walk(function.parameters) + walk(function.returnType) + } + public mutating func walk(_ constructor: ExportedConstructor) { + walk(constructor.parameters) + } + public mutating func walk(_ skeleton: ExportedSkeleton) { + for function in skeleton.functions { + walk(function) + } + for klass in skeleton.classes { + if let constructor = klass.constructor { + walk(constructor.parameters) + } + for method in klass.methods { + walk(method) + } + for property in klass.properties { + walk(property.type) + } + } + for proto in skeleton.protocols { + for method in proto.methods { + walk(method) + } + for property in proto.properties { + walk(property.type) + } + } + for structDecl in skeleton.structs { + for property in structDecl.properties { + walk(property.type) + } + if let constructor = structDecl.constructor { + walk(constructor.parameters) + } + for method in structDecl.methods { + walk(method) + } + } + for enumDecl in skeleton.enums { + for enumCase in enumDecl.cases { + for associatedValue in enumCase.associatedValues { + walk(associatedValue.type) + } + } + for method in enumDecl.staticMethods { + walk(method) + } + for property in enumDecl.staticProperties { + walk(property.type) + } + } + } + public mutating func walk(_ function: ImportedFunctionSkeleton) { + walk(function.parameters) + walk(function.returnType) + } + public mutating func walk(_ skeleton: ImportedModuleSkeleton) { + for fileSkeleton in skeleton.children { + for getter in fileSkeleton.globalGetters { + walk(getter.type) + } + for setter in fileSkeleton.globalSetters { + walk(setter.type) + } + for function in fileSkeleton.functions { + walk(function) + } + for type in fileSkeleton.types { + if let constructor = type.constructor { + walk(constructor.parameters) + } + for getter in type.getters { + walk(getter.type) + } + for setter in type.setters { + walk(setter.type) + } + for method in type.methods + type.staticMethods { + walk(method) + } + } + } + } + public mutating func walk(_ skeleton: BridgeJSSkeleton) { + if let exported = skeleton.exported { + walk(exported) + } + if let imported = skeleton.imported { + walk(imported) + } } } -public struct Effects: Codable { +public struct Effects: Codable, Equatable, Sendable { public var isAsync: Bool public var isThrows: Bool + public var isStatic: Bool - public init(isAsync: Bool, isThrows: Bool) { + public init(isAsync: Bool, isThrows: Bool, isStatic: Bool = false) { self.isAsync = isAsync self.isThrows = isThrows + self.isStatic = isStatic + } +} + +// MARK: - Static Function Context + +public enum StaticContext: Codable, Equatable, Sendable { + case className(String) + case structName(String) + case enumName(String) + case namespaceEnum(String) +} + +// MARK: - Struct Skeleton + +public struct StructField: Codable, Equatable, Sendable { + public let name: String + public let type: BridgeType + + public init(name: String, type: BridgeType) { + self.name = name + self.type = type + } +} + +public struct ExportedStruct: Codable, Equatable, Sendable { + public let name: String + public let swiftCallName: String + public let explicitAccessControl: String? + public var properties: [ExportedProperty] + public var constructor: ExportedConstructor? + public var methods: [ExportedFunction] + public let namespace: [String]? + + public init( + name: String, + swiftCallName: String, + explicitAccessControl: String?, + properties: [ExportedProperty] = [], + constructor: ExportedConstructor? = nil, + methods: [ExportedFunction] = [], + namespace: [String]? + ) { + self.name = name + self.swiftCallName = swiftCallName + self.explicitAccessControl = explicitAccessControl + self.properties = properties + self.constructor = constructor + self.methods = methods + self.namespace = namespace + } +} + +// MARK: - Enum Skeleton + +public struct AssociatedValue: Codable, Equatable, Sendable { + public let label: String? + public let type: BridgeType + + public init(label: String?, type: BridgeType) { + self.label = label + self.type = type + } +} + +public struct EnumCase: Codable, Equatable, Sendable { + public let name: String + public let rawValue: String? + public let associatedValues: [AssociatedValue] + + public var isSimple: Bool { + associatedValues.isEmpty + } + public init(name: String, rawValue: String?, associatedValues: [AssociatedValue] = []) { + self.name = name + self.rawValue = rawValue + self.associatedValues = associatedValues + } +} + +extension EnumCase { + /// Generates JavaScript/TypeScript value representation for this enum case + public func jsValue(rawType: SwiftEnumRawType?, index: Int) -> String { + guard let rawType = rawType else { + return "\(index)" + } + let rawValue = self.rawValue ?? self.name + switch rawType { + case .string: + return "\"\(rawValue)\"" + case .bool: + return rawValue.lowercased() == "true" ? "true" : "false" + case .float, .double, .int, .int32, .int64, .uint, .uint32, .uint64: + return rawValue + } + } +} + +public enum EnumEmitStyle: String, Codable, Sendable { + case const + case tsEnum +} + +public struct ExportedEnum: Codable, Equatable, Sendable { + public static let valuesSuffix = "Values" + public static let objectSuffix = "Object" + + public let name: String + public let swiftCallName: String + public let tsFullPath: String + public let explicitAccessControl: String? + public var cases: [EnumCase] + public let rawType: SwiftEnumRawType? + public let namespace: [String]? + public let emitStyle: EnumEmitStyle + public var staticMethods: [ExportedFunction] + public var staticProperties: [ExportedProperty] = [] + public var enumType: EnumType { + if cases.isEmpty { + return .namespace + } else if cases.allSatisfy(\.isSimple) { + return rawType != nil ? .rawValue : .simple + } else { + return .associatedValue + } + } + + public var valuesName: String { + emitStyle == .tsEnum ? name : "\(name)\(Self.valuesSuffix)" + } + + public var objectTypeName: String { + "\(name)\(Self.objectSuffix)" + } + + public init( + name: String, + swiftCallName: String, + tsFullPath: String, + explicitAccessControl: String?, + cases: [EnumCase], + rawType: SwiftEnumRawType?, + namespace: [String]?, + emitStyle: EnumEmitStyle, + staticMethods: [ExportedFunction] = [], + staticProperties: [ExportedProperty] = [] + ) { + self.name = name + self.swiftCallName = swiftCallName + self.tsFullPath = tsFullPath + self.explicitAccessControl = explicitAccessControl + self.cases = cases + self.rawType = rawType + self.namespace = namespace + self.emitStyle = emitStyle + self.staticMethods = staticMethods + self.staticProperties = staticProperties } } +public enum EnumType: String, Codable, Sendable { + case simple // enum Direction { case north, south, east } + case rawValue // enum Mode: String { case light = "light" } + case associatedValue // enum Result { case success(String), failure(Int) } + case namespace // enum Utils { } (empty, used as namespace) +} + // MARK: - Exported Skeleton -public struct ExportedFunction: Codable { +public struct ExportedProtocolProperty: Codable, Equatable, Sendable { + public let name: String + public let type: BridgeType + public let isReadonly: Bool + + public init( + name: String, + type: BridgeType, + isReadonly: Bool + ) { + self.name = name + self.type = type + self.isReadonly = isReadonly + } +} + +public struct ExportedProtocol: Codable, Equatable { + public let name: String + public let methods: [ExportedFunction] + public let properties: [ExportedProtocolProperty] + public let namespace: [String]? + + public init( + name: String, + methods: [ExportedFunction], + properties: [ExportedProtocolProperty] = [], + namespace: [String]? = nil + ) { + self.name = name + self.methods = methods + self.properties = properties + self.namespace = namespace + } +} + +public struct ExportedFunction: Codable, Equatable, Sendable { public var name: String public var abiName: String public var parameters: [Parameter] public var returnType: BridgeType public var effects: Effects public var namespace: [String]? + public var staticContext: StaticContext? public init( name: String, @@ -48,7 +606,8 @@ public struct ExportedFunction: Codable { parameters: [Parameter], returnType: BridgeType, effects: Effects, - namespace: [String]? = nil + namespace: [String]? = nil, + staticContext: StaticContext? = nil ) { self.name = name self.abiName = abiName @@ -56,29 +615,39 @@ public struct ExportedFunction: Codable { self.returnType = returnType self.effects = effects self.namespace = namespace + self.staticContext = staticContext } } public struct ExportedClass: Codable { public var name: String + public var swiftCallName: String + public var explicitAccessControl: String? public var constructor: ExportedConstructor? public var methods: [ExportedFunction] + public var properties: [ExportedProperty] public var namespace: [String]? public init( name: String, + swiftCallName: String, + explicitAccessControl: String?, constructor: ExportedConstructor? = nil, methods: [ExportedFunction], + properties: [ExportedProperty] = [], namespace: [String]? = nil ) { self.name = name + self.swiftCallName = swiftCallName + self.explicitAccessControl = explicitAccessControl self.constructor = constructor self.methods = methods + self.properties = properties self.namespace = namespace } } -public struct ExportedConstructor: Codable { +public struct ExportedConstructor: Codable, Equatable, Sendable { public var abiName: String public var parameters: [Parameter] public var effects: Effects @@ -92,90 +661,561 @@ public struct ExportedConstructor: Codable { } } +public struct ExportedProperty: Codable, Equatable, Sendable { + public var name: String + public var type: BridgeType + public var isReadonly: Bool + public var isStatic: Bool + public var namespace: [String]? + public var staticContext: StaticContext? + + public init( + name: String, + type: BridgeType, + isReadonly: Bool = false, + isStatic: Bool = false, + namespace: [String]? = nil, + staticContext: StaticContext? = nil + ) { + self.name = name + self.type = type + self.isReadonly = isReadonly + self.isStatic = isStatic + self.namespace = namespace + self.staticContext = staticContext + } + + public func callName(prefix: String? = nil) -> String { + if let staticContext = staticContext { + switch staticContext { + case .className(let baseName), .enumName(let baseName), .structName(let baseName), + .namespaceEnum(let baseName): + return "\(baseName).\(name)" + } + } + if let prefix = prefix { + return "\(prefix).\(name)" + } + return name + } + + public func getterAbiName(className: String = "") -> String { + return ABINameGenerator.generateABIName( + baseName: name, + namespace: namespace, + staticContext: isStatic ? staticContext : nil, + operation: "get", + className: isStatic ? nil : className + ) + } + + public func setterAbiName(className: String = "") -> String { + return ABINameGenerator.generateABIName( + baseName: name, + namespace: namespace, + staticContext: isStatic ? staticContext : nil, + operation: "set", + className: isStatic ? nil : className + ) + } +} + public struct ExportedSkeleton: Codable { - public let moduleName: String - public let functions: [ExportedFunction] - public let classes: [ExportedClass] + public var functions: [ExportedFunction] + public var classes: [ExportedClass] + public var enums: [ExportedEnum] + public var structs: [ExportedStruct] + public var protocols: [ExportedProtocol] + /// Whether to expose exported APIs to the global namespace. + /// + /// When `true`, exported functions, classes, and namespaces are available + /// via `globalThis` in JavaScript. When `false`, they are only available + /// through the exports object. + public var exposeToGlobal: Bool - public init(moduleName: String, functions: [ExportedFunction], classes: [ExportedClass]) { - self.moduleName = moduleName + public init( + functions: [ExportedFunction], + classes: [ExportedClass], + enums: [ExportedEnum], + structs: [ExportedStruct] = [], + protocols: [ExportedProtocol] = [], + exposeToGlobal: Bool + ) { self.functions = functions self.classes = classes + self.enums = enums + self.structs = structs + self.protocols = protocols + self.exposeToGlobal = exposeToGlobal + } + + public mutating func append(_ other: ExportedSkeleton) { + self.functions.append(contentsOf: other.functions) + self.classes.append(contentsOf: other.classes) + self.enums.append(contentsOf: other.enums) + self.structs.append(contentsOf: other.structs) + self.protocols.append(contentsOf: other.protocols) + assert(self.exposeToGlobal == other.exposeToGlobal) + } + + public var isEmpty: Bool { + functions.isEmpty && classes.isEmpty && enums.isEmpty && structs.isEmpty && protocols.isEmpty } } // 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, + 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 + } + public func abiName(context: ImportedTypeSkeleton?) -> String { - return context.map { "bjs_\($0.name)_\(name)" } ?? "bjs_\(name)" + return abiName(context: context, operation: nil) + } + + public func abiName(context: ImportedTypeSkeleton?, operation: String?) -> String { + return ABINameGenerator.generateImportedABIName( + baseName: name, + context: context, + operation: operation + ) } } public struct ImportedConstructorSkeleton: Codable { public let parameters: [Parameter] + public init(parameters: [Parameter]) { + self.parameters = parameters + } + public func abiName(context: ImportedTypeSkeleton) -> String { - return "bjs_\(context.name)_init" + return ABINameGenerator.generateImportedABIName( + baseName: "init", + context: context + ) } } -public struct ImportedPropertySkeleton: Codable { +public struct ImportedGetterSkeleton: Codable { public let name: String - public let isReadonly: Bool + /// 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) + public let functionName: String? + + 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 + } + + public func abiName(context: ImportedTypeSkeleton?) -> String { + if let functionName = functionName { + return ABINameGenerator.generateImportedABIName( + baseName: functionName, + context: context, + operation: nil + ) + } + return ABINameGenerator.generateImportedABIName( + baseName: name, + context: context, + operation: "get" + ) + } +} + +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) + public let functionName: String? - public func getterAbiName(context: ImportedTypeSkeleton) -> String { - return "bjs_\(context.name)_\(name)_get" + 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 } - public func setterAbiName(context: ImportedTypeSkeleton) -> String { - return "bjs_\(context.name)_\(name)_set" + public func abiName(context: ImportedTypeSkeleton?) -> String { + if let functionName = functionName { + return ABINameGenerator.generateImportedABIName( + baseName: functionName, + context: context, + operation: nil + ) + } + return ABINameGenerator.generateImportedABIName( + baseName: name, + context: context, + operation: "set" + ) } } 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 properties: [ImportedPropertySkeleton] + /// Static methods available on the JavaScript constructor. + public var staticMethods: [ImportedFunctionSkeleton] + public let getters: [ImportedGetterSkeleton] + public let setters: [ImportedSetterSkeleton] public let documentation: String? + + public init( + name: String, + jsName: String? = nil, + from: JSImportFrom? = nil, + constructor: ImportedConstructorSkeleton? = nil, + methods: [ImportedFunctionSkeleton] = [], + staticMethods: [ImportedFunctionSkeleton] = [], + getters: [ImportedGetterSkeleton] = [], + setters: [ImportedSetterSkeleton] = [], + documentation: String? = nil + ) { + self.name = name + self.jsName = jsName + self.from = from + self.constructor = constructor + self.methods = methods + self.staticMethods = staticMethods + self.getters = getters + self.setters = setters + self.documentation = documentation + } } public struct ImportedFileSkeleton: Codable { public let functions: [ImportedFunctionSkeleton] public let types: [ImportedTypeSkeleton] + /// Global-scope imported properties (e.g. `@JSGetter var console: JSConsole`) + public let globalGetters: [ImportedGetterSkeleton] + /// Global-scope imported properties (future use; not currently emitted by macros) + public let globalSetters: [ImportedSetterSkeleton] + + public init( + functions: [ImportedFunctionSkeleton], + types: [ImportedTypeSkeleton], + globalGetters: [ImportedGetterSkeleton] = [], + globalSetters: [ImportedSetterSkeleton] = [] + ) { + self.functions = functions + self.types = types + self.globalGetters = globalGetters + self.globalSetters = globalSetters + } + + private enum CodingKeys: String, CodingKey { + case functions + case types + case globalGetters + case globalSetters + } + + public init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.functions = try container.decode([ImportedFunctionSkeleton].self, forKey: .functions) + self.types = try container.decode([ImportedTypeSkeleton].self, forKey: .types) + self.globalGetters = try container.decodeIfPresent([ImportedGetterSkeleton].self, forKey: .globalGetters) ?? [] + self.globalSetters = try container.decodeIfPresent([ImportedSetterSkeleton].self, forKey: .globalSetters) ?? [] + } + + public func encode(to encoder: any Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(functions, forKey: .functions) + try container.encode(types, forKey: .types) + if !globalGetters.isEmpty { + try container.encode(globalGetters, forKey: .globalGetters) + } + if !globalSetters.isEmpty { + try container.encode(globalSetters, forKey: .globalSetters) + } + } + + public var isEmpty: Bool { + functions.isEmpty && types.isEmpty && globalGetters.isEmpty && globalSetters.isEmpty + } } public struct ImportedModuleSkeleton: Codable { - public let moduleName: String public var children: [ImportedFileSkeleton] - public init(moduleName: String, children: [ImportedFileSkeleton]) { - self.moduleName = moduleName + public init(children: [ImportedFileSkeleton]) { self.children = children } } +// MARK: - Closure signature collection visitor + +public struct ClosureSignatureCollectorVisitor: BridgeTypeVisitor { + public var signatures: Set = [] + + public init(signatures: Set = []) { + self.signatures = signatures + } + + public mutating func visitClosure(_ signature: ClosureSignature, useJSTypedClosure: Bool) { + signatures.insert(signature) + } +} + +// MARK: - Unified Skeleton + +/// Unified skeleton containing both exported and imported API definitions +public struct BridgeJSSkeleton: Codable { + public let moduleName: String + public let exported: ExportedSkeleton? + public let imported: ImportedModuleSkeleton? + + public init(moduleName: String, exported: ExportedSkeleton? = nil, imported: ImportedModuleSkeleton? = nil) { + self.moduleName = moduleName + self.exported = exported + self.imported = imported + } +} + +// MARK: - BridgeType extension + extension BridgeType { + /// Maps Swift primitive type names to BridgeType. Returns nil for unknown types. + public init?(swiftType: String) { + switch swiftType { + case "Int": + self = .int + case "UInt": + self = .uint + case "Float": + self = .float + case "Double": + self = .double + case "String": + self = .string + case "Bool": + self = .bool + case "JSValue": + self = .jsValue + case "Void": + 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 + } + } + public var abiReturnType: WasmCoreType? { 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 case .jsObject: return .i32 + case .jsValue: return nil case .swiftHeapObject: // UnsafeMutableRawPointer is returned as an i32 pointer return .pointer + case .unsafePointer: + return .pointer + case .nullable: + return nil + case .caseEnum: + return .i32 + case .rawValueEnum(_, let rawType): + return rawType.wasmCoreType + case .associatedValueEnum: + return nil + case .namespaceEnum: + return nil + case .swiftProtocol: + // Protocols pass JSObject IDs as Int32 + return .i32 + case .swiftStruct: + // Structs use stack-based return (no direct WASM return type) + return nil + case .closure: + // Closures pass callback ID as Int32 + return .i32 + case .array: + // Arrays use stack-based return with length prefix (no direct WASM return type) + return nil + case .dictionary: + // Dictionaries use stack-based return with entry count (no direct WASM return type) + return nil + } + } + + /// Returns true if this type is optional (nullable with null or undefined). + public var isOptional: Bool { + if case .nullable = self { return true } + return false + } + + /// Simplified Swift ABI-style mangled name + /// https://github.com/swiftlang/swift/blob/main/docs/ABI/Mangling.rst#types + 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" + case .bool: return "Sb" + case .void: return "y" + case .jsObject(let name): + let typeName = name ?? "JSObject" + return "\(typeName.count)\(typeName)C" + case .jsValue: + return "7JSValueV" + 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 .nullable(let wrapped, let kind): + let prefix = kind == .null ? "Sq" : "Su" + return "\(prefix)\(wrapped.mangleTypeName)" + case .caseEnum(let name), + .rawValueEnum(let name, _), + .associatedValueEnum(let name), + .namespaceEnum(let name): + return "\(name.count)\(name)O" + case .swiftProtocol(let name): + return "\(name.count)\(name)P" + case .swiftStruct(let name): + return "\(name.count)\(name)V" + case .closure(let signature, let useJSTypedClosure): + let params = + signature.parameters.isEmpty + ? "y" + : signature.parameters.map { $0.mangleTypeName }.joined() + return "K\(params)_\(signature.returnType.mangleTypeName)\(useJSTypedClosure ? "J" : "")" + case .array(let elementType): + // Array mangling: "Sa" prefix followed by element type + return "Sa\(elementType.mangleTypeName)" + case .dictionary(let valueType): + // Dictionary mangling: "SD" prefix followed by value type (key is always String) + return "SD\(valueType.mangleTypeName)" + } + } + + /// Determines if an optional type requires side-channel communication for protocol property returns + /// + /// Side channels are needed when the wrapped type cannot be directly returned via WASM, + /// or when we need to distinguish null from absent value for certain primitives. + public func usesSideChannelForOptionalReturn() -> Bool { + guard case .nullable(let wrappedType, _) = self else { + return false + } + + switch wrappedType { + case .string, .int, .float, .double, .jsObject, .swiftProtocol: + return true + case .rawValueEnum(_, let rawType): + switch rawType { + case .string, .int, .float, .double: + return true + default: + return false + } + case .bool, .caseEnum, .swiftHeapObject, .associatedValueEnum: + return false + default: + return false + } + } +} + +extension WasmCoreType { + /// Returns a Swift statement that returns a placeholder value for this Wasm core type. + public var swiftReturnPlaceholderStmt: String { + switch self { + case .i32: return "return 0" + case .i64: return "return 0" + case .f32: return "return 0.0" + case .f64: return "return 0.0" + case .pointer: return "return UnsafeMutableRawPointer(bitPattern: -1).unsafelyUnwrapped" } } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift b/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift index dba6fe47c..a71aaee44 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift @@ -1,14 +1,22 @@ @preconcurrency import func Foundation.exit @preconcurrency import func Foundation.fputs +@preconcurrency import func Foundation.open +@preconcurrency import func Foundation.strerror @preconcurrency import var Foundation.stderr +@preconcurrency import var Foundation.errno +@preconcurrency import var Foundation.O_WRONLY +@preconcurrency import var Foundation.O_CREAT +@preconcurrency import var Foundation.O_TRUNC @preconcurrency import struct Foundation.URL @preconcurrency import struct Foundation.Data @preconcurrency import struct Foundation.ObjCBool @preconcurrency import class Foundation.JSONEncoder +@preconcurrency import class Foundation.FileHandle @preconcurrency import class Foundation.FileManager @preconcurrency import class Foundation.JSONDecoder @preconcurrency import class Foundation.ProcessInfo import SwiftParser +import SwiftSyntax #if canImport(BridgeJSCore) import BridgeJSCore @@ -16,8 +24,11 @@ import BridgeJSCore #if canImport(BridgeJSSkeleton) import BridgeJSSkeleton #endif -#if canImport(TS2Skeleton) -import TS2Skeleton +#if canImport(TS2Swift) +import TS2Swift +#endif +#if canImport(BridgeJSUtilities) +import BridgeJSUtilities #endif /// BridgeJS Tool @@ -29,10 +40,7 @@ import TS2Skeleton /// 2. Export: Generate JavaScript bindings for Swift declarations /// /// Usage: -/// For importing TypeScript: -/// $ bridge-js import --module-name --output-swift --output-skeleton --project -/// For exporting Swift: -/// $ bridge-js export --output-swift --output-skeleton +/// $ bridge-js generate --module-name --target-dir --output-swift --output-skeleton [--output-import-swift ] [--output-import-skeleton ] [--project ] ... [...] /// /// This tool is intended to be used through the Swift Package Manager plugin system /// and is not typically called directly by end users. @@ -40,19 +48,26 @@ import TS2Skeleton static func help() -> String { return """ - Usage: \(CommandLine.arguments.first ?? "bridge-js-tool") [options] + Usage: \(CommandLine.arguments.first ?? "bridge-js-tool") generate [options] ... - Subcommands: - import Generate binding code to import TypeScript APIs into Swift - export Generate binding code to export Swift APIs to JavaScript + Generate bridge code for both exporting Swift APIs and importing TypeScript APIs. + Input files can be Swift source files (for export) or macro-annotated Swift files (for import). """ } static func main() throws { do { - try run() + try Profiling.with(Profiling.make) { + try run() + } } catch { - printStderr("error: \(error)") + if let diagError = error as? BridgeJSCoreDiagnosticError { + diagError.diagnostics.forEach { file, diagnostic in + printStderr(diagnostic.formattedDescription(fileName: file)) + } + } else { + printStderr("error: \(error)") + } exit(1) } } @@ -69,16 +84,16 @@ import TS2Skeleton ) } switch subcommand { - case "import": + case "generate": let parser = ArgumentParser( singleDashOptions: [:], doubleDashOptions: [ "module-name": OptionRule( - help: "The name of the module to import the TypeScript API into", + help: "The name of the module", required: true ), "always-write": OptionRule( - help: "Always write the output files even if no APIs are imported", + help: "Always write the output files even if no APIs are found", required: false ), "verbose": OptionRule( @@ -89,14 +104,13 @@ import TS2Skeleton help: "The SwiftPM package target directory", required: true ), - "output-swift": OptionRule(help: "The output file path for the Swift source code", required: true), - "output-skeleton": OptionRule( - help: "The output file path for the skeleton of the imported TypeScript APIs", + "output-dir": OptionRule( + help: "The output directory for generated code", required: true ), "project": OptionRule( - help: "The path to the TypeScript project configuration file", - required: true + help: "The path to the TypeScript project configuration file (required for .d.ts files)", + required: false ), ] ) @@ -104,130 +118,147 @@ import TS2Skeleton arguments: Array(arguments.dropFirst()) ) let progress = ProgressReporting(verbose: doubleDashOptions["verbose"] == "true") - var importer = ImportTS(progress: progress, moduleName: doubleDashOptions["module-name"]!) + let moduleName = doubleDashOptions["module-name"]! let targetDirectory = URL(fileURLWithPath: doubleDashOptions["target-dir"]!) + let outputDirectory = URL(fileURLWithPath: doubleDashOptions["output-dir"]!) let config = try BridgeJSConfig.load(targetDirectory: targetDirectory) let nodePath: URL = try config.findTool("node", targetDirectory: targetDirectory) - for inputFile in positionalArguments { - if inputFile.hasSuffix(".json") { - let sourceURL = URL(fileURLWithPath: inputFile) - let skeleton = try JSONDecoder().decode( - ImportedFileSkeleton.self, - from: Data(contentsOf: sourceURL) + + let bridgeJsDtsPath = targetDirectory.appending(path: "bridge-js.d.ts") + 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 withSpan("invokeTS2Swift") { + _ = try invokeTS2Swift( + dtsFile: primaryDtsPath, + globalDtsFiles: globalDtsFiles, + tsconfigPath: tsconfigPath, + nodePath: nodePath, + progress: progress, + outputPath: bridgeJSMacrosPath.path ) - importer.addSkeleton(skeleton) - } else if inputFile.hasSuffix(".d.ts") { - let tsconfigPath = URL(fileURLWithPath: doubleDashOptions["project"]!) - try importer.addSourceFile(inputFile, tsconfigPath: tsconfigPath.path, nodePath: nodePath) } + generatedMacrosPath = bridgeJSMacrosPath.path } - let outputSwift = try importer.finalize() - let shouldWrite = doubleDashOptions["always-write"] == "true" || outputSwift != nil - guard shouldWrite else { - progress.print("No imported TypeScript APIs found") - return + var inputFiles = withSpan("Collecting Swift files") { + return inputSwiftFiles(targetDirectory: targetDirectory, positionalArguments: positionalArguments) } - let outputSwiftURL = URL(fileURLWithPath: doubleDashOptions["output-swift"]!) - try FileManager.default.createDirectory( - at: outputSwiftURL.deletingLastPathComponent(), - withIntermediateDirectories: true, - attributes: nil - ) - try (outputSwift ?? "").write(to: outputSwiftURL, atomically: true, encoding: .utf8) - - let outputSkeletonsURL = URL(fileURLWithPath: doubleDashOptions["output-skeleton"]!) - try FileManager.default.createDirectory( - at: outputSkeletonsURL.deletingLastPathComponent(), - withIntermediateDirectories: true, - attributes: nil + // 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, + exposeToGlobal: config.exposeToGlobal ) - let encoder = JSONEncoder() - encoder.outputFormatting = [.prettyPrinted, .sortedKeys] - try encoder.encode(importer.skeleton).write(to: outputSkeletonsURL) + for inputFile in inputFiles.sorted() { + try withSpan("Parsing \(inputFile)") { + let inputURL = URL(fileURLWithPath: inputFile) + // Skip directories (e.g. .docc catalogs included in target.sourceFiles) + var isDirectory: ObjCBool = false + if FileManager.default.fileExists(atPath: inputFile, isDirectory: &isDirectory), + isDirectory.boolValue + { + return + } + let content = try String(contentsOf: inputURL, encoding: .utf8) + if hasBridgeJSSkipComment(content) { + return + } + + let sourceFile = Parser.parse(source: content) + swiftToSkeleton.addSourceFile(sourceFile, inputFilePath: inputFile) + } + } - progress.print( - """ - Imported TypeScript APIs: - - \(outputSwiftURL.path) - - \(outputSkeletonsURL.path) - """ - ) - case "export": - let parser = ArgumentParser( - singleDashOptions: [:], - doubleDashOptions: [ - "module-name": OptionRule( - help: "The name of the module for external function references", - required: true - ), - "output-skeleton": OptionRule( - help: "The output file path for the skeleton of the exported Swift APIs", - required: true - ), - "output-swift": OptionRule(help: "The output file path for the Swift source code", required: true), - "always-write": OptionRule( - help: "Always write the output files even if no APIs are exported", - required: false - ), - "verbose": OptionRule( - help: "Print verbose output", - required: false - ), - ] - ) - let (positionalArguments, _, doubleDashOptions) = try parser.parse( - arguments: Array(arguments.dropFirst()) - ) - let progress = ProgressReporting(verbose: doubleDashOptions["verbose"] == "true") - let exporter = ExportSwift(progress: progress, moduleName: doubleDashOptions["module-name"]!) - for inputFile in positionalArguments.sorted() { - let sourceURL = URL(fileURLWithPath: inputFile) - guard sourceURL.pathExtension == "swift" else { continue } - let sourceContent = try String(contentsOf: sourceURL, encoding: .utf8) - let sourceFile = Parser.parse(source: sourceContent) - try exporter.addSourceFile(sourceFile, sourceURL.path) + let skeleton = try withSpan("SwiftToSkeleton.finalize") { + return try swiftToSkeleton.finalize() } - // Finalize the export - let output = try exporter.finalize() - let outputSwiftURL = URL(fileURLWithPath: doubleDashOptions["output-swift"]!) - let outputSkeletonURL = URL(fileURLWithPath: doubleDashOptions["output-skeleton"]!) + var exporter: ExportSwift? + if let skeleton = skeleton.exported { + exporter = ExportSwift( + progress: progress, + moduleName: moduleName, + skeleton: skeleton + ) + } + var importer: ImportTS? + if let skeleton = skeleton.imported { + importer = ImportTS( + progress: progress, + moduleName: moduleName, + skeleton: skeleton + ) + } - let shouldWrite = doubleDashOptions["always-write"] == "true" || output != nil - guard shouldWrite else { - progress.print("No exported Swift APIs found") - return + // Generate unified closure support for both import/export to avoid duplicate symbols when concatenating. + let closureSupport = try withSpan("ClosureCodegen.renderSupport") { + return try ClosureCodegen().renderSupport(for: skeleton) } - // Create the output directory if it doesn't exist - try FileManager.default.createDirectory( - at: outputSwiftURL.deletingLastPathComponent(), - withIntermediateDirectories: true, - attributes: nil - ) - try FileManager.default.createDirectory( - at: outputSkeletonURL.deletingLastPathComponent(), - withIntermediateDirectories: true, - attributes: nil - ) + let importResult = try withSpan("ImportTS.finalize") { + return try importer?.finalize() + } + let exportResult = try withSpan("ExportSwift.finalize") { + return try exporter?.finalize() + } - // Write the output Swift file - try (output?.outputSwift ?? "").write(to: outputSwiftURL, atomically: true, encoding: .utf8) + // Combine and write unified Swift output + let outputSwiftURL = outputDirectory.appending(path: "BridgeJS.swift") + let combinedSwift = [closureSupport, exportResult, importResult].compactMap { $0 } + let outputSwift = combineGeneratedSwift(combinedSwift) + let shouldWrite = doubleDashOptions["always-write"] == "true" || !outputSwift.isEmpty + if shouldWrite { + try withSpan("Writing output Swift") { + try FileManager.default.createDirectory( + at: outputSwiftURL.deletingLastPathComponent(), + withIntermediateDirectories: true, + attributes: nil + ) + try writeIfChanged(outputSwift, to: outputSwiftURL) + } + } - if let outputSkeleton = output?.outputSkeleton { - // Write the output skeleton file + // Write unified skeleton + let outputSkeletonURL = outputDirectory.appending(path: "JavaScript/BridgeJS.json") + try withSpan("Writing output skeleton") { + try FileManager.default.createDirectory( + at: outputSkeletonURL.deletingLastPathComponent(), + withIntermediateDirectories: true, + attributes: nil + ) let encoder = JSONEncoder() encoder.outputFormatting = [.prettyPrinted, .sortedKeys] - let outputSkeletonData = try encoder.encode(outputSkeleton) - try outputSkeletonData.write(to: outputSkeletonURL) + let skeletonData = try encoder.encode(skeleton) + try writeIfChanged(skeletonData, to: outputSkeletonURL) + } + + if skeleton.exported != nil || skeleton.imported != nil { + progress.print("Generated BridgeJS code") } - progress.print( + case "export", "import": + throw BridgeJSToolError( """ - Exported Swift APIs: - - \(outputSwiftURL.path) - - \(outputSkeletonURL.path) + Error: Subcommands 'export' and 'import' have been unified into 'generate'. + + \(BridgeJSTool.help()) """ ) default: @@ -254,6 +285,80 @@ private func printStderr(_ message: String) { fputs(message + "\n", stderr) } +private func hasBridgeJSSkipComment(_ content: String) -> Bool { + BridgeJSGeneratedFile.hasSkipComment(content) +} + +private func writeIfChanged(_ content: String, to url: URL) throws { + let existing = try? String(contentsOf: url, encoding: .utf8) + guard existing != content else { return } + try content.write(to: url, atomically: true, encoding: .utf8) +} + +private func writeIfChanged(_ data: Data, to url: URL) throws { + let existing = try? Data(contentsOf: url) + guard existing != data else { return } + try data.write(to: url) +} + +private func combineGeneratedSwift(_ pieces: [String]) -> String { + let trimmedPieces = + pieces + .map { $0.trimmingCharacters(in: .newlines) } + .filter { !$0.isEmpty } + guard !trimmedPieces.isEmpty else { return "" } + + return ([BridgeJSGeneratedFile.swiftPreamble] + trimmedPieces).joined(separator: "\n\n") +} + +private func recursivelyCollectSwiftFiles(from directory: URL) -> [URL] { + var swiftFiles: [URL] = [] + let fileManager = FileManager.default + + guard + let enumerator = fileManager.enumerator( + at: directory, + includingPropertiesForKeys: [.isRegularFileKey, .isDirectoryKey], + options: [.skipsHiddenFiles] + ) + else { + return [] + } + + for case let fileURL as URL in enumerator { + if fileURL.pathExtension == "swift" { + let resourceValues = try? fileURL.resourceValues(forKeys: [.isRegularFileKey]) + if resourceValues?.isRegularFile == true { + swiftFiles.append(fileURL) + } + } + } + + return swiftFiles.sorted { $0.path < $1.path } +} + +private func inputSwiftFiles(targetDirectory: URL, positionalArguments: [String]) -> [String] { + if positionalArguments.isEmpty { + return recursivelyCollectSwiftFiles(from: targetDirectory).map(\.path) + } + return positionalArguments +} + +extension Profiling { + static func make() -> Profiling? { + guard let outputPath = ProcessInfo.processInfo.environment["BRIDGEJS_PROFILING"] else { + return nil + } + let fd = open(outputPath, O_WRONLY | O_CREAT | O_TRUNC, 0o644) + guard fd >= 0 else { + let error = String(cString: strerror(errno)) + fatalError("Failed to open profiling output file \(outputPath): \(error)") + } + let output = FileHandle(fileDescriptor: fd, closeOnDealloc: true) + return Profiling.traceEvent(output: { output.write($0.data(using: .utf8) ?? Data()) }) + } +} + // MARK: - Minimal Argument Parsing struct OptionRule { diff --git a/Plugins/BridgeJS/Sources/BridgeJSToolInternal/BridgeJSToolInternal.swift b/Plugins/BridgeJS/Sources/BridgeJSToolInternal/BridgeJSToolInternal.swift new file mode 100644 index 000000000..8a6a6b7b4 --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSToolInternal/BridgeJSToolInternal.swift @@ -0,0 +1,137 @@ +@preconcurrency import struct Foundation.URL +@preconcurrency import struct Foundation.Data +@preconcurrency import class Foundation.JSONEncoder +@preconcurrency import class Foundation.JSONDecoder +@preconcurrency import class Foundation.FileHandle +import SwiftParser +import SwiftSyntax + +import BridgeJSCore +import BridgeJSSkeleton +import BridgeJSLink +import BridgeJSUtilities + +import ArgumentParser + +@main struct BridgeJSToolInternal: ParsableCommand { + + static let configuration = CommandConfiguration( + commandName: "bridge-js-tool-internal", + abstract: "BridgeJS Tool Internal", + version: "0.1.0", + subcommands: [ + EmitSkeleton.self, + EmitSwiftThunks.self, + EmitJS.self, + EmitDTS.self, + ] + ) + + static func readData(from file: String) throws -> Data { + if file == "-" { + return try FileHandle.standardInput.readToEnd() ?? Data() + } else { + return try Data(contentsOf: URL(fileURLWithPath: file)) + } + } + + struct EmitSkeleton: ParsableCommand { + static let configuration = CommandConfiguration( + commandName: "emit-skeleton", + abstract: "Emit the BridgeJS skeleton", + ) + + @Argument(help: "The input files to emit the BridgeJS skeleton from") + var inputFiles: [String] + + func run() throws { + let swiftToSkeleton = SwiftToSkeleton( + progress: ProgressReporting(verbose: false), + moduleName: "InternalModule", + exposeToGlobal: false + ) + for inputFile in inputFiles.sorted() { + let content = try String(decoding: readData(from: inputFile), as: UTF8.self) + if BridgeJSGeneratedFile.hasSkipComment(content) { + continue + } + let sourceFile = Parser.parse(source: content) + swiftToSkeleton.addSourceFile(sourceFile, inputFilePath: inputFile) + } + let skeleton = try swiftToSkeleton.finalize() + let encoder = JSONEncoder() + encoder.outputFormatting = [.prettyPrinted, .sortedKeys] + let skeletonData = try encoder.encode(skeleton) + print(String(data: skeletonData, encoding: .utf8)!) + } + } + + struct EmitSwiftThunks: ParsableCommand { + static let configuration = CommandConfiguration( + commandName: "emit-swift-thunks", + abstract: "Emit the Swift thunks", + ) + @Argument(help: "The skeleton file to emit the Swift thunks from") + var skeletonFile: String + + func run() throws { + let skeletonData = try readData(from: skeletonFile) + let skeleton = try JSONDecoder().decode(BridgeJSSkeleton.self, from: skeletonData) + let moduleName = "InternalModule" + let exported = try skeleton.exported.flatMap { + try ExportSwift( + progress: ProgressReporting(verbose: false), + moduleName: moduleName, + skeleton: $0 + ).finalize() + } + let imported = try skeleton.imported.flatMap { + try ImportTS( + progress: ProgressReporting(verbose: false), + moduleName: moduleName, + skeleton: $0 + ).finalize() + } + let combinedSwift = [exported, imported].compactMap { $0 } + print(combinedSwift.joined(separator: "\n\n")) + } + } + + static func linkSkeletons(skeletonFiles: [String]) throws -> (outputJs: String, outputDts: String) { + var skeletons: [BridgeJSSkeleton] = [] + for skeletonFile in skeletonFiles.sorted() { + let skeletonData = try readData(from: skeletonFile) + skeletons.append(try JSONDecoder().decode(BridgeJSSkeleton.self, from: skeletonData)) + } + let link = BridgeJSLink(skeletons: skeletons, sharedMemory: false) + return try link.link() + } + + struct EmitJS: ParsableCommand { + static let configuration = CommandConfiguration( + commandName: "emit-js", + abstract: "Emit the JavaScript glue code", + ) + @Argument(help: "The skeleton files to emit the JavaScript glue code from") + var skeletonFiles: [String] + + func run() throws { + let (outputJs, _) = try linkSkeletons(skeletonFiles: skeletonFiles) + print(outputJs) + } + } + + struct EmitDTS: ParsableCommand { + static let configuration = CommandConfiguration( + commandName: "emit-dts", + abstract: "Emit the TypeScript type definitions", + ) + @Argument(help: "The skeleton files to emit the TypeScript type definitions from") + var skeletonFiles: [String] + + func run() throws { + let (_, outputDts) = try linkSkeletons(skeletonFiles: skeletonFiles) + print(outputDts) + } + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift b/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift new file mode 100644 index 000000000..68c07f225 --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift @@ -0,0 +1,82 @@ +extension String { + public var capitalizedFirstLetter: String { + guard !isEmpty else { return self } + return prefix(1).uppercased() + dropFirst() + } +} + +public enum BridgeJSGeneratedFile { + /// The magic comment to skip processing by BridgeJS. + public static let skipLine = "// bridge-js: skip" + + public static func hasSkipComment(_ content: String) -> Bool { + content.starts(with: skipLine + "\n") + } + + public static var swiftPreamble: String { + // The generated Swift file itself should not be processed by BridgeJS again. + """ + \(skipLine) + // 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(BridgeJS) import JavaScriptKit + """ + } +} + +/// A printer for code fragments. +public final class CodeFragmentPrinter { + public private(set) var lines: [String] = [] + private var indentLevel: Int = 0 + + public init(header: String = "") { + self.lines.append(contentsOf: header.split(separator: "\n").map { String($0) }) + } + + public func nextLine() { + lines.append("") + } + + public func write(_ line: S) { + if line.isEmpty { + // Empty lines should not have trailing spaces + lines.append("") + return + } + lines.append(String(repeating: " ", count: indentLevel * 4) + String(line)) + } + + public func write(lines: [String]) { + for line in lines { + write(line) + } + } + + public func write(contentsOf printer: CodeFragmentPrinter) { + self.write(lines: printer.lines) + } + + public func write(multilineString: String) { + for line in multilineString.split(separator: "\n") { + write(line) + } + } + + public func indent() { + indentLevel += 1 + } + + public func unindent() { + indentLevel -= 1 + } + + public func indent(_ body: () throws -> Void) rethrows { + indentLevel += 1 + try body() + indentLevel -= 1 + } +} diff --git a/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/README.md b/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/README.md deleted file mode 100644 index de6806350..000000000 --- a/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# ts2skeleton - -This script analyzes the TypeScript type definitions and produces a structured JSON output with skeleton information that can be used to generate Swift bindings. diff --git a/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/package.json b/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/package.json deleted file mode 100644 index 48fb77cfc..000000000 --- a/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "type": "module", - "dependencies": { - "typescript": "5.8.2" - }, - "bin": { - "ts2skeleton": "./bin/ts2skeleton.js" - } -} diff --git a/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/src/cli.js b/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/src/cli.js deleted file mode 100644 index f708082c6..000000000 --- a/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/src/cli.js +++ /dev/null @@ -1,151 +0,0 @@ -// @ts-check -import * as fs from 'fs'; -import { TypeProcessor } from './processor.js'; -import { parseArgs } from 'util'; -import ts from 'typescript'; -import path from 'path'; - -class DiagnosticEngine { - /** - * @param {string} level - */ - constructor(level) { - const levelInfo = DiagnosticEngine.LEVELS[level]; - if (!levelInfo) { - throw new Error(`Invalid log level: ${level}`); - } - this.minLevel = levelInfo.level; - /** @type {ts.FormatDiagnosticsHost} */ - this.formattHost = { - getCanonicalFileName: (fileName) => fileName, - getNewLine: () => ts.sys.newLine, - getCurrentDirectory: () => ts.sys.getCurrentDirectory(), - }; - } - - /** - * @param {readonly ts.Diagnostic[]} diagnostics - */ - tsDiagnose(diagnostics) { - const message = ts.formatDiagnosticsWithColorAndContext(diagnostics, this.formattHost); - console.log(message); - } - - static LEVELS = { - "verbose": { - color: '\x1b[34m', - level: 0, - }, - "info": { - color: '\x1b[32m', - level: 1, - }, - "warning": { - color: '\x1b[33m', - level: 2, - }, - "error": { - color: '\x1b[31m', - level: 3, - }, - } - - /** - * @param {keyof typeof DiagnosticEngine.LEVELS} level - * @param {string} message - * @param {ts.Node | undefined} node - */ - print(level, message, node = undefined) { - const levelInfo = DiagnosticEngine.LEVELS[level]; - if (levelInfo.level < this.minLevel) { - return; - } - const color = levelInfo.color; - if (node) { - const sourceFile = node.getSourceFile(); - const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); - const location = sourceFile.fileName + ":" + (line + 1) + ":" + (character); - process.stderr.write(`${location}: ${color}${level}\x1b[0m: ${message}\n`); - } else { - process.stderr.write(`${color}${level}\x1b[0m: ${message}\n`); - } - } -} - -function printUsage() { - console.error('Usage: ts2skeleton -p [-o output.json]'); -} - -/** - * Main function to run the CLI - * @param {string[]} args - Command-line arguments - * @returns {void} - */ -export function main(args) { - // Parse command line arguments - const options = parseArgs({ - args, - options: { - output: { - type: 'string', - short: 'o', - }, - project: { - type: 'string', - short: 'p', - }, - "log-level": { - type: 'string', - default: 'info', - }, - }, - allowPositionals: true - }) - - if (options.positionals.length !== 1) { - printUsage(); - process.exit(1); - } - - const tsconfigPath = options.values.project; - if (!tsconfigPath) { - printUsage(); - process.exit(1); - } - - const filePath = options.positionals[0]; - const diagnosticEngine = new DiagnosticEngine(options.values["log-level"] || "info"); - - diagnosticEngine.print("verbose", `Processing ${filePath}...`); - - // Create TypeScript program and process declarations - const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile); - const configParseResult = ts.parseJsonConfigFileContent( - configFile.config, - ts.sys, - path.dirname(path.resolve(tsconfigPath)) - ); - - if (configParseResult.errors.length > 0) { - diagnosticEngine.tsDiagnose(configParseResult.errors); - process.exit(1); - } - - const program = TypeProcessor.createProgram(filePath, configParseResult.options); - const diagnostics = program.getSemanticDiagnostics(); - if (diagnostics.length > 0) { - diagnosticEngine.tsDiagnose(diagnostics); - process.exit(1); - } - - const processor = new TypeProcessor(program.getTypeChecker(), diagnosticEngine); - const results = processor.processTypeDeclarations(program, filePath); - - // Write results to file or stdout - const jsonOutput = JSON.stringify(results, null, 2); - if (options.values.output) { - fs.writeFileSync(options.values.output, jsonOutput); - } else { - process.stdout.write(jsonOutput, "utf-8"); - } -} diff --git a/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/src/index.d.ts b/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/src/index.d.ts deleted file mode 100644 index b53e2420c..000000000 --- a/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/src/index.d.ts +++ /dev/null @@ -1,49 +0,0 @@ -export type BridgeType = - | { "int": {} } - | { "float": {} } - | { "double": {} } - | { "string": {} } - | { "bool": {} } - | { "jsObject": { "_0": string } | {} } - | { "void": {} } - -export type Parameter = { - name: string; - type: BridgeType; -} - -export type Effects = { - isAsync: boolean; -} - -export type ImportFunctionSkeleton = { - name: string; - parameters: Parameter[]; - returnType: BridgeType; - effects: Effects; - documentation: string | undefined; -} - -export type ImportConstructorSkeleton = { - parameters: Parameter[]; -} - -export type ImportPropertySkeleton = { - name: string; - type: BridgeType; - isReadonly: boolean; - documentation: string | undefined; -} - -export type ImportTypeSkeleton = { - name: string; - documentation: string | undefined; - constructor?: ImportConstructorSkeleton; - properties: ImportPropertySkeleton[]; - methods: ImportFunctionSkeleton[]; -} - -export type ImportSkeleton = { - functions: ImportFunctionSkeleton[]; - types: ImportTypeSkeleton[]; -} diff --git a/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/src/processor.js b/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/src/processor.js deleted file mode 100644 index aeaf6a2db..000000000 --- a/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/src/processor.js +++ /dev/null @@ -1,445 +0,0 @@ -/** - * TypeScript type processing functionality - * @module processor - */ - -// @ts-check -import ts from 'typescript'; - -/** @typedef {import('./index').ImportSkeleton} ImportSkeleton */ -/** @typedef {import('./index').ImportFunctionSkeleton} ImportFunctionSkeleton */ -/** @typedef {import('./index').ImportTypeSkeleton} ImportTypeSkeleton */ -/** @typedef {import('./index').ImportPropertySkeleton} ImportPropertySkeleton */ -/** @typedef {import('./index').ImportConstructorSkeleton} ImportConstructorSkeleton */ -/** @typedef {import('./index').Parameter} Parameter */ -/** @typedef {import('./index').BridgeType} BridgeType */ - -/** - * @typedef {{ - * print: (level: "warning" | "error", message: string, node?: ts.Node) => void, - * }} DiagnosticEngine - */ - -/** - * TypeScript type processor class - */ -export class TypeProcessor { - /** - * Create a TypeScript program from a d.ts file - * @param {string} filePath - Path to the d.ts file - * @param {ts.CompilerOptions} options - Compiler options - * @returns {ts.Program} TypeScript program object - */ - static createProgram(filePath, options) { - const host = ts.createCompilerHost(options); - return ts.createProgram([filePath], options, host); - } - - /** - * @param {ts.TypeChecker} checker - TypeScript type checker - * @param {DiagnosticEngine} diagnosticEngine - Diagnostic engine - */ - constructor(checker, diagnosticEngine, options = { - inheritIterable: true, - inheritArraylike: true, - inheritPromiselike: true, - addAllParentMembersToClass: true, - replaceAliasToFunction: true, - replaceRankNFunction: true, - replaceNewableFunction: true, - noExtendsInTyprm: false, - }) { - this.checker = checker; - this.diagnosticEngine = diagnosticEngine; - this.options = options; - - /** @type {Map} */ - this.processedTypes = new Map(); - /** @type {Map} Seen position by type */ - this.seenTypes = new Map(); - /** @type {ImportFunctionSkeleton[]} */ - this.functions = []; - /** @type {ImportTypeSkeleton[]} */ - this.types = []; - } - - /** - * Process type declarations from a TypeScript program - * @param {ts.Program} program - TypeScript program - * @param {string} inputFilePath - Path to the input file - * @returns {ImportSkeleton} Processed type declarations - */ - processTypeDeclarations(program, inputFilePath) { - const sourceFiles = program.getSourceFiles().filter( - sf => !sf.isDeclarationFile || sf.fileName === inputFilePath - ); - - for (const sourceFile of sourceFiles) { - if (sourceFile.fileName.includes('node_modules/typescript/lib')) continue; - - Error.stackTraceLimit = 100; - - try { - sourceFile.forEachChild(node => { - this.visitNode(node); - - for (const [type, node] of this.seenTypes) { - this.seenTypes.delete(type); - const typeString = this.checker.typeToString(type); - const members = type.getProperties(); - if (members) { - const type = this.visitStructuredType(typeString, members); - this.types.push(type); - } else { - this.types.push(this.createUnknownType(typeString)); - } - } - }); - } catch (error) { - this.diagnosticEngine.print("error", `Error processing ${sourceFile.fileName}: ${error.message}`); - } - } - - return { functions: this.functions, types: this.types }; - } - - /** - * Create an unknown type - * @param {string} typeString - Type string - * @returns {ImportTypeSkeleton} Unknown type - */ - createUnknownType(typeString) { - return { - name: typeString, - documentation: undefined, - properties: [], - methods: [], - constructor: undefined, - }; - } - - /** - * Visit a node and process it - * @param {ts.Node} node - The node to visit - */ - visitNode(node) { - if (ts.isFunctionDeclaration(node)) { - const func = this.visitFunctionLikeDecl(node); - if (func && node.name) { - this.functions.push({ ...func, name: node.name.getText() }); - } - } else if (ts.isClassDeclaration(node)) { - const cls = this.visitClassDecl(node); - if (cls) this.types.push(cls); - } - } - - /** - * Process a function declaration into ImportFunctionSkeleton format - * @param {ts.SignatureDeclaration} node - The function node - * @returns {ImportFunctionSkeleton | null} Processed function - * @private - */ - visitFunctionLikeDecl(node) { - if (!node.name) return null; - - const signature = this.checker.getSignatureFromDeclaration(node); - if (!signature) return null; - - /** @type {Parameter[]} */ - const parameters = []; - for (const p of signature.getParameters()) { - const bridgeType = this.visitSignatureParameter(p, node); - parameters.push(bridgeType); - } - - const returnType = signature.getReturnType(); - const bridgeReturnType = this.visitType(returnType, node); - const documentation = this.getFullJSDocText(node); - - return { - name: node.name.getText(), - parameters, - returnType: bridgeReturnType, - documentation, - effects: { isAsync: false }, - }; - } - - /** - * Get the full JSDoc text from a node - * @param {ts.Node} node - The node to get the JSDoc text from - * @returns {string | undefined} The full JSDoc text - */ - getFullJSDocText(node) { - const docs = ts.getJSDocCommentsAndTags(node); - const parts = []; - for (const doc of docs) { - if (ts.isJSDoc(doc)) { - parts.push(doc.comment ?? ""); - } - } - if (parts.length === 0) return undefined; - return parts.join("\n"); - } - - /** - * @param {ts.ConstructorDeclaration} node - * @returns {ImportConstructorSkeleton | null} - */ - visitConstructorDecl(node) { - const signature = this.checker.getSignatureFromDeclaration(node); - if (!signature) return null; - - const parameters = []; - for (const p of signature.getParameters()) { - const bridgeType = this.visitSignatureParameter(p, node); - parameters.push(bridgeType); - } - - return { parameters }; - } - - /** - * @param {ts.PropertyDeclaration | ts.PropertySignature} node - * @returns {ImportPropertySkeleton | null} - */ - visitPropertyDecl(node) { - if (!node.name) return null; - const type = this.checker.getTypeAtLocation(node) - const bridgeType = this.visitType(type, node); - const isReadonly = node.modifiers?.some(m => m.kind === ts.SyntaxKind.ReadonlyKeyword) ?? false; - const documentation = this.getFullJSDocText(node); - return { name: node.name.getText(), type: bridgeType, isReadonly, documentation }; - } - - /** - * @param {ts.Symbol} symbol - * @param {ts.Node} node - * @returns {Parameter} - */ - visitSignatureParameter(symbol, node) { - const type = this.checker.getTypeOfSymbolAtLocation(symbol, node); - const bridgeType = this.visitType(type, node); - return { name: symbol.name, type: bridgeType }; - } - - /** - * @param {ts.ClassDeclaration} node - * @returns {ImportTypeSkeleton | null} - */ - visitClassDecl(node) { - if (!node.name) return null; - - const name = node.name.text; - const properties = []; - const methods = []; - /** @type {ImportConstructorSkeleton | undefined} */ - let constructor = undefined; - - for (const member of node.members) { - if (ts.isPropertyDeclaration(member)) { - const property = this.visitPropertyDecl(member); - if (property) properties.push(property); - } else if (ts.isMethodDeclaration(member)) { - const decl = this.visitFunctionLikeDecl(member); - if (decl) methods.push(decl); - } else if (ts.isConstructorDeclaration(member)) { - const decl = this.visitConstructorDecl(member); - if (decl) constructor = decl; - } - } - - const documentation = this.getFullJSDocText(node); - return { - name, - constructor, - properties, - methods, - documentation, - }; - } - - /** - * @param {ts.SymbolFlags} flags - * @returns {string[]} - */ - debugSymbolFlags(flags) { - const result = []; - for (const key in ts.SymbolFlags) { - const val = (ts.SymbolFlags)[key]; - if (typeof val === "number" && (flags & val) !== 0) { - result.push(key); - } - } - return result; - } - - /** - * @param {ts.TypeFlags} flags - * @returns {string[]} - */ - debugTypeFlags(flags) { - const result = []; - for (const key in ts.TypeFlags) { - const val = (ts.TypeFlags)[key]; - if (typeof val === "number" && (flags & val) !== 0) { - result.push(key); - } - } - return result; - } - - /** - * @param {string} name - * @param {ts.Symbol[]} members - * @returns {ImportTypeSkeleton} - */ - visitStructuredType(name, members) { - /** @type {ImportPropertySkeleton[]} */ - const properties = []; - /** @type {ImportFunctionSkeleton[]} */ - const methods = []; - /** @type {ImportConstructorSkeleton | undefined} */ - let constructor = undefined; - for (const symbol of members) { - if (symbol.flags & ts.SymbolFlags.Property) { - for (const decl of symbol.getDeclarations() ?? []) { - if (ts.isPropertyDeclaration(decl) || ts.isPropertySignature(decl)) { - const property = this.visitPropertyDecl(decl); - if (property) properties.push(property); - } else if (ts.isMethodSignature(decl)) { - const method = this.visitFunctionLikeDecl(decl); - if (method) methods.push(method); - } - } - } else if (symbol.flags & ts.SymbolFlags.Method) { - for (const decl of symbol.getDeclarations() ?? []) { - if (!ts.isMethodSignature(decl)) { - continue; - } - const method = this.visitFunctionLikeDecl(decl); - if (method) methods.push(method); - } - } else if (symbol.flags & ts.SymbolFlags.Constructor) { - for (const decl of symbol.getDeclarations() ?? []) { - if (!ts.isConstructorDeclaration(decl)) { - continue; - } - const ctor = this.visitConstructorDecl(decl); - if (ctor) constructor = ctor; - } - } - } - return { name, properties, methods, constructor, documentation: undefined }; - } - - /** - * Convert TypeScript type string to BridgeType - * @param {ts.Type} type - TypeScript type string - * @param {ts.Node} node - Node - * @returns {BridgeType} Bridge type - * @private - */ - visitType(type, node) { - // Treat A and A as the same type - if (isTypeReference(type)) { - type = type.target; - } - const maybeProcessed = this.processedTypes.get(type); - if (maybeProcessed) { - return maybeProcessed; - } - /** - * @param {ts.Type} type - * @returns {BridgeType} - */ - const convert = (type) => { - /** @type {Record} */ - const typeMap = { - "number": { "double": {} }, - "string": { "string": {} }, - "boolean": { "bool": {} }, - "void": { "void": {} }, - "any": { "jsObject": {} }, - "unknown": { "jsObject": {} }, - "null": { "void": {} }, - "undefined": { "void": {} }, - "bigint": { "int": {} }, - "object": { "jsObject": {} }, - "symbol": { "jsObject": {} }, - "never": { "void": {} }, - "Promise": { - "jsObject": { - "_0": "JSPromise" - } - }, - }; - const typeString = type.getSymbol()?.name ?? this.checker.typeToString(type); - if (typeMap[typeString]) { - return typeMap[typeString]; - } - - if (this.checker.isArrayType(type) || this.checker.isTupleType(type) || type.getCallSignatures().length > 0) { - return { "jsObject": {} }; - } - // "a" | "b" -> string - if (this.checker.isTypeAssignableTo(type, this.checker.getStringType())) { - return { "string": {} }; - } - if (type.isTypeParameter()) { - return { "jsObject": {} }; - } - - const typeName = this.deriveTypeName(type); - if (!typeName) { - this.diagnosticEngine.print("warning", `Unknown non-nominal type: ${typeString}`, node); - return { "jsObject": {} }; - } - this.seenTypes.set(type, node); - return { "jsObject": { "_0": typeName } }; - } - const bridgeType = convert(type); - this.processedTypes.set(type, bridgeType); - return bridgeType; - } - - /** - * Derive the type name from a type - * @param {ts.Type} type - TypeScript type - * @returns {string | undefined} Type name - * @private - */ - deriveTypeName(type) { - const aliasSymbol = type.aliasSymbol; - if (aliasSymbol) { - return aliasSymbol.name; - } - const typeSymbol = type.getSymbol(); - if (typeSymbol) { - return typeSymbol.name; - } - return undefined; - } -} - -/** - * @param {ts.Type} type - * @returns {type is ts.ObjectType} - */ -function isObjectType(type) { - // @ts-ignore - return typeof type.objectFlags === "number"; -} - -/** - * - * @param {ts.Type} type - * @returns {type is ts.TypeReference} - */ -function isTypeReference(type) { - return ( - isObjectType(type) && - (type.objectFlags & ts.ObjectFlags.Reference) !== 0 - ); -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/README.md b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/README.md new file mode 100644 index 000000000..b2dbe6a6a --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/README.md @@ -0,0 +1,3 @@ +# ts2swift + +This script analyzes the TypeScript type definitions and produces macro-annotated Swift declarations that can be fed into BridgeJS for glue generation. diff --git a/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/bin/ts2skeleton.js b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/bin/ts2swift.js old mode 100755 new mode 100644 similarity index 53% rename from Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/bin/ts2skeleton.js rename to Plugins/BridgeJS/Sources/TS2Swift/JavaScript/bin/ts2swift.js index ba926a889..cc94fce3c --- a/Plugins/BridgeJS/Sources/TS2Skeleton/JavaScript/bin/ts2skeleton.js +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/bin/ts2swift.js @@ -2,11 +2,10 @@ // @ts-check /** - * Main entry point for the ts2skeleton tool + * Main entry point for the ts2swift tool * - * This script analyzes the TypeScript type definitions and produces a structured - * JSON output with skeleton information that can be used to generate Swift - * bindings. + * This script analyzes the TypeScript type definitions and produces macro-annotated + * Swift declarations that can be used to generate Swift bindings. */ import { main } from "../src/cli.js" diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/package.json b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/package.json new file mode 100644 index 000000000..0c8a50c48 --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/package.json @@ -0,0 +1,13 @@ +{ + "type": "module", + "dependencies": { + "typescript": "5.8.2" + }, + "bin": { + "ts2swift": "./bin/ts2swift.js" + }, + "scripts": { + "test": "vitest run", + "tsc": "tsc --noEmit" + } +} diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js new file mode 100644 index 000000000..25d88b828 --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js @@ -0,0 +1,256 @@ +// @ts-check +import * as fs from 'fs'; +import os from 'os'; +import path from 'path'; +import { parseArgs } from 'util'; +import ts from 'typescript'; +import { TypeProcessor } from './processor.js'; + +class DiagnosticEngine { + /** + * @param {keyof typeof DiagnosticEngine.LEVELS} level + */ + constructor(level) { + const levelInfo = DiagnosticEngine.LEVELS[level]; + if (!levelInfo) { + throw new Error(`Invalid log level: ${level}`); + } + this.minLevel = levelInfo.level; + /** @type {ts.FormatDiagnosticsHost} */ + this.formattHost = { + getCanonicalFileName: (fileName) => fileName, + getNewLine: () => ts.sys.newLine, + getCurrentDirectory: () => ts.sys.getCurrentDirectory(), + }; + } + + /** + * @param {readonly ts.Diagnostic[]} diagnostics + */ + tsDiagnose(diagnostics) { + const message = ts.formatDiagnosticsWithColorAndContext(diagnostics, this.formattHost); + process.stderr.write(message, "utf-8"); + } + + static LEVELS = { + "verbose": { + color: '\x1b[34m', + level: 0, + }, + "info": { + color: '\x1b[32m', + level: 1, + }, + "warning": { + color: '\x1b[33m', + level: 2, + }, + "error": { + color: '\x1b[31m', + level: 3, + }, + } + + /** + * @param {keyof typeof DiagnosticEngine.LEVELS} level + * @param {string} message + * @param {ts.Node | undefined} node + */ + print(level, message, node = undefined) { + const levelInfo = DiagnosticEngine.LEVELS[level]; + if (levelInfo.level < this.minLevel) { + return; + } + const color = levelInfo.color; + if (node) { + const sourceFile = node.getSourceFile(); + const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); + const location = sourceFile.fileName + ":" + (line + 1) + ":" + (character); + process.stderr.write(`${location}: ${color}${level}\x1b[0m: ${message}\n`); + } else { + process.stderr.write(`${color}${level}\x1b[0m: ${message}\n`); + } + } +} + +function printUsage() { + console.error(`Usage: ts2swift [options] + + Path to a .d.ts file, or "-" to read from stdin + +Options: + -o, --output Write Swift to . Use "-" for stdout (default). + -p, --project Path to tsconfig.json (default: tsconfig.json). + --global Add a .d.ts as a global declaration file (repeatable). + --log-level One of: verbose, info, warning, error (default: info). + -h, --help Show this help. + +Examples: + ts2swift lib.d.ts + ts2swift lib.d.ts -o Generated.swift + ts2swift lib.d.ts -p ./tsconfig.build.json -o Sources/Bridge/API.swift + cat lib.d.ts | ts2swift - -o Generated.swift + ts2swift lib.d.ts --global dom.d.ts --global lib.d.ts +`); +} + +/** + * Run ts2swift for a single input file (programmatic API, no process I/O). + * @param {string[]} filePaths - Paths to the .d.ts files + * @param {{ tsconfigPath: string, logLevel?: keyof typeof DiagnosticEngine.LEVELS, globalFiles?: string[] }} options + * @returns {string} Generated Swift source + * @throws {Error} on parse/type-check errors (diagnostics are included in the message) + */ +export function run(filePaths, options) { + const { tsconfigPath, logLevel = 'info', globalFiles = [] } = options; + const diagnosticEngine = new DiagnosticEngine(logLevel); + + const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile); + const configParseResult = ts.parseJsonConfigFileContent( + configFile.config, + ts.sys, + path.dirname(path.resolve(tsconfigPath)) + ); + + if (configParseResult.errors.length > 0) { + const message = ts.formatDiagnosticsWithColorAndContext(configParseResult.errors, { + getCanonicalFileName: (fileName) => fileName, + getNewLine: () => ts.sys.newLine, + getCurrentDirectory: () => ts.sys.getCurrentDirectory(), + }); + throw new Error(`TypeScript config/parse errors:\n${message}`); + } + + const program = TypeProcessor.createProgram([...filePaths, ...globalFiles], configParseResult.options); + const diagnostics = program.getSemanticDiagnostics(); + if (diagnostics.length > 0) { + const message = ts.formatDiagnosticsWithColorAndContext(diagnostics, { + getCanonicalFileName: (fileName) => fileName, + getNewLine: () => ts.sys.newLine, + getCurrentDirectory: () => ts.sys.getCurrentDirectory(), + }); + throw new Error(`TypeScript semantic errors:\n${message}`); + } + + 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(BridgeJS) import JavaScriptKit", + "", + "", + ].join("\n"); + + /** @type {string[]} */ + const bodies = []; + const globalFileSet = new Set(globalFiles); + for (const inputPath of [...filePaths, ...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; + return hasAny ? prelude + bodies.join("\n\n") + "\n" : ""; +} + +/** + * Main function to run the CLI + * @param {string[]} args - Command-line arguments + * @returns {void} + */ +export function main(args) { + const options = parseArgs({ + args, + options: { + output: { + type: 'string', + short: 'o', + }, + project: { + type: 'string', + short: 'p', + }, + global: { + type: 'string', + multiple: true, + }, + "log-level": { + type: 'string', + default: 'info', + }, + help: { + type: 'boolean', + short: 'h', + }, + }, + allowPositionals: true + }) + + if (options.values.help) { + printUsage(); + process.exit(0); + } + + if (options.positionals.length !== 1) { + printUsage(); + process.exit(1); + } + + /** @type {string[]} */ + let filePaths = options.positionals; + /** @type {(() => void)[]} cleanup functions to run after completion */ + const cleanups = []; + + if (filePaths[0] === '-') { + const content = fs.readFileSync(0, 'utf-8'); + const stdinTempPath = path.join(os.tmpdir(), `ts2swift-stdin-${process.pid}-${Date.now()}.d.ts`); + fs.writeFileSync(stdinTempPath, content); + cleanups.push(() => fs.unlinkSync(stdinTempPath)); + filePaths = [stdinTempPath]; + } + const logLevel = /** @type {keyof typeof DiagnosticEngine.LEVELS} */ ((() => { + const logLevel = options.values["log-level"] || "info"; + if (!Object.keys(DiagnosticEngine.LEVELS).includes(logLevel)) { + console.error(`Invalid log level: ${logLevel}. Valid levels are: ${Object.keys(DiagnosticEngine.LEVELS).join(", ")}`); + process.exit(1); + } + return logLevel; + })()); + const globalFiles = options.values.global || []; + const tsconfigPath = options.values.project || "tsconfig.json"; + + const diagnosticEngine = new DiagnosticEngine(logLevel); + diagnosticEngine.print("verbose", `Processing ${filePaths.join(", ")}`); + + let swiftOutput; + try { + swiftOutput = run(filePaths, { tsconfigPath, logLevel, globalFiles }); + } catch (/** @type {unknown} */ err) { + if (err instanceof Error) { + diagnosticEngine.print("error", err.message); + } else { + diagnosticEngine.print("error", String(err)); + } + process.exit(1); + } finally { + for (const cleanup of cleanups) { + cleanup(); + } + } + // Write to file or stdout + if (options.values.output && options.values.output !== "-") { + if (swiftOutput.length > 0) { + fs.mkdirSync(path.dirname(options.values.output), { recursive: true }); + fs.writeFileSync(options.values.output, swiftOutput); + } + } else { + process.stdout.write(swiftOutput, "utf-8"); + } +} diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/index.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/index.d.ts new file mode 100644 index 000000000..97af7b169 --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/index.d.ts @@ -0,0 +1,4 @@ +export type Parameter = { + name: string; + type: string; +} diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/processor.js b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/processor.js new file mode 100644 index 000000000..53216a78c --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/processor.js @@ -0,0 +1,1227 @@ +/** + * TypeScript type processing functionality + * @module processor + */ + +// @ts-check +import ts from 'typescript'; + +/** @typedef {import('./index.d.ts').Parameter} Parameter */ + +/** + * @typedef {{ + * print: (level: "warning" | "error", message: string, node?: ts.Node) => void, + * }} DiagnosticEngine + */ + +/** + * TypeScript type processor class + */ +export class TypeProcessor { + /** + * Create a TypeScript program from a d.ts file + * @param {string[]} filePaths - Paths to the d.ts file + * @param {ts.CompilerOptions} options - Compiler options + * @returns {ts.Program} TypeScript program object + */ + static createProgram(filePaths, options) { + const host = ts.createCompilerHost(options); + return ts.createProgram(filePaths, { + ...options, + noCheck: true, + skipLibCheck: true, + }, host); + } + + /** + * @param {ts.TypeChecker} checker - TypeScript type checker + * @param {DiagnosticEngine} diagnosticEngine - Diagnostic engine + */ + constructor(checker, diagnosticEngine, options = { + defaultImportFromGlobal: false, + }) { + this.checker = checker; + this.diagnosticEngine = diagnosticEngine; + this.options = options; + + /** @type {Map} */ + this.processedTypes = new Map(); + /** @type {Map} Seen position by type */ + this.seenTypes = new Map(); + /** @type {string[]} Collected Swift code lines */ + this.swiftLines = []; + /** @type {Set} */ + this.emittedEnumNames = new Set(); + /** @type {Set} */ + this.emittedStructuredTypeNames = new Set(); + + /** @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)); + } + + /** + * Process type declarations from a TypeScript program and render Swift code + * @param {ts.Program} program - TypeScript program + * @param {string} inputFilePath - Path to the input file + * @returns {{ content: string, hasAny: boolean }} Rendered Swift code + */ + processTypeDeclarations(program, inputFilePath) { + const sourceFiles = program.getSourceFiles().filter( + sf => !sf.isDeclarationFile || sf.fileName === inputFilePath + ); + + for (const sourceFile of sourceFiles) { + if (sourceFile.fileName.includes('node_modules/typescript/lib')) continue; + + Error.stackTraceLimit = 100; + + try { + sourceFile.forEachChild(node => { + this.visitNode(node); + + for (const [type, node] of this.seenTypes) { + this.seenTypes.delete(type); + if (this.isEnumType(type)) { + this.visitEnumType(type, node); + continue; + } + const members = type.getProperties(); + if (members) { + this.visitStructuredType(type, node, members); + } + } + }); + } catch (/** @type {unknown} */ error) { + if (error instanceof Error) { + this.diagnosticEngine.print("error", `Error processing ${sourceFile.fileName}: ${error.message}`); + } else { + this.diagnosticEngine.print("error", `Error processing ${sourceFile.fileName}: ${String(error)}`); + } + } + } + + const content = this.swiftLines.join("\n").trimEnd() + "\n"; + const hasAny = content.trim().length > 0; + return { content, hasAny }; + } + + + /** + * Visit a node and process it + * @param {ts.Node} node - The node to visit + */ + visitNode(node) { + if (ts.isFunctionDeclaration(node)) { + 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)) { + this.visitExportDeclaration(node); + } + } + + /** + * Visit an export declaration and process re-exports like: + * - export { Thing } from "./module"; + * - export { Thing as Alias } from "./module"; + * - export * from "./module"; + * @param {ts.ExportDeclaration} node + */ + visitExportDeclaration(node) { + if (!node.moduleSpecifier) return; + + const moduleSymbol = this.checker.getSymbolAtLocation(node.moduleSpecifier); + if (!moduleSymbol) { + this.diagnosticEngine.print("warning", "Failed to resolve module for export declaration", node); + return; + } + + /** @type {ts.Symbol[]} */ + let targetSymbols = []; + + if (!node.exportClause) { + // export * from "..." + targetSymbols = this.checker.getExportsOfModule(moduleSymbol); + } else if (ts.isNamedExports(node.exportClause)) { + const moduleExports = this.checker.getExportsOfModule(moduleSymbol); + for (const element of node.exportClause.elements) { + const originalName = element.propertyName?.text ?? element.name.text; + + const match = moduleExports.find(s => s.name === originalName); + if (match) { + targetSymbols.push(match); + continue; + } + + // Fallback for unusual bindings/resolution failures. + const fallback = this.checker.getSymbolAtLocation(element.propertyName ?? element.name); + if (fallback) { + targetSymbols.push(fallback); + continue; + } + + this.diagnosticEngine.print("warning", `Failed to resolve re-exported symbol '${originalName}'`, node); + } + } else { + // export * as ns from "..." is not currently supported by BridgeJS imports. + return; + } + + for (const symbol of targetSymbols) { + const declarations = symbol.getDeclarations() ?? []; + for (const declaration of declarations) { + // Avoid duplicate emission when the same declaration is reached via multiple re-exports. + const sourceFile = declaration.getSourceFile(); + const key = `${sourceFile.fileName}:${declaration.pos}:${declaration.end}`; + if (this.visitedDeclarationKeys.has(key)) continue; + this.visitedDeclarationKeys.add(key); + + this.visitNode(declaration); + } + } + } + + /** + * 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.emitDocComment(decl, { indent: "" }); + this.swiftLines.push(`${annotation} var ${swiftVarName}: ${swiftType}`); + this.swiftLines.push(""); + } + } + + /** + * @param {ts.Type} type + * @returns {boolean} + * @private + */ + isEnumType(type) { + const symbol = type.getSymbol() ?? type.aliasSymbol; + if (!symbol) return false; + return (symbol.flags & ts.SymbolFlags.Enum) !== 0; + } + + /** + * @param {ts.EnumDeclaration} node + * @private + */ + visitEnumDeclaration(node) { + const name = node.name?.text; + if (!name) return; + this.emitEnumFromDeclaration(name, node, node); + } + + /** + * @param {ts.Type} type + * @param {ts.Node} node + * @private + */ + visitEnumType(type, node) { + const symbol = type.getSymbol() ?? type.aliasSymbol; + const name = symbol?.name; + if (!name) return; + const decl = symbol?.getDeclarations()?.find(d => ts.isEnumDeclaration(d)); + if (!decl || !ts.isEnumDeclaration(decl)) { + this.diagnosticEngine.print("warning", `Enum declaration not found for type: ${name}`, node); + return; + } + this.emitEnumFromDeclaration(name, decl, node); + } + + /** + * @param {string} enumName + * @param {ts.EnumDeclaration} decl + * @param {ts.Node} diagnosticNode + * @private + */ + emitEnumFromDeclaration(enumName, decl, diagnosticNode) { + if (this.emittedEnumNames.has(enumName)) return; + this.emittedEnumNames.add(enumName); + + const members = decl.members ?? []; + this.emitDocComment(decl, { indent: "" }); + if (members.length === 0) { + this.diagnosticEngine.print("warning", `Empty enum is not supported: ${enumName}`, diagnosticNode); + this.swiftLines.push(`typealias ${this.renderIdentifier(enumName)} = String`); + this.swiftLines.push(""); + return; + } + + /** @type {{ name: string, raw: string }[]} */ + const stringMembers = []; + /** @type {{ name: string, raw: number }[]} */ + const intMembers = []; + let canBeStringEnum = true; + let canBeIntEnum = true; + let nextAutoValue = 0; + + for (const member of members) { + const rawMemberName = member.name.getText(); + const unquotedName = rawMemberName.replace(/^["']|["']$/g, ""); + const swiftCaseNameBase = makeValidSwiftIdentifier(unquotedName, { emptyFallback: "_case" }); + + if (member.initializer && ts.isStringLiteral(member.initializer)) { + stringMembers.push({ name: swiftCaseNameBase, raw: member.initializer.text }); + canBeIntEnum = false; + continue; + } + + if (member.initializer && ts.isNumericLiteral(member.initializer)) { + const rawValue = Number(member.initializer.text); + if (!Number.isInteger(rawValue)) { + canBeIntEnum = false; + } else { + intMembers.push({ name: swiftCaseNameBase, raw: rawValue }); + nextAutoValue = rawValue + 1; + canBeStringEnum = false; + continue; + } + } + + if (!member.initializer) { + intMembers.push({ name: swiftCaseNameBase, raw: nextAutoValue }); + nextAutoValue += 1; + canBeStringEnum = false; + continue; + } + + canBeStringEnum = false; + canBeIntEnum = false; + } + const swiftEnumName = this.renderTypeIdentifier(enumName); + const dedupeNames = (/** @type {{ name: string, raw: string | number }[]} */ items) => { + const seen = new Map(); + return items.map(item => { + const count = seen.get(item.name) ?? 0; + seen.set(item.name, count + 1); + if (count === 0) return item; + return { ...item, name: `${item.name}_${count + 1}` }; + }); + }; + + if (canBeStringEnum && stringMembers.length > 0) { + this.swiftLines.push(`enum ${swiftEnumName}: String {`); + for (const { name, raw } of dedupeNames(stringMembers)) { + if (typeof raw !== "string") { + this.diagnosticEngine.print("warning", `Invalid string literal: ${raw}`, diagnosticNode); + continue; + } + this.swiftLines.push(` case ${this.renderIdentifier(name)} = "${raw.replaceAll("\"", "\\\\\"")}"`); + } + this.swiftLines.push("}"); + this.swiftLines.push(`extension ${swiftEnumName}: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum {}`); + this.swiftLines.push(""); + return; + } + + if (canBeIntEnum && intMembers.length > 0) { + this.swiftLines.push(`enum ${swiftEnumName}: Int {`); + for (const { name, raw } of dedupeNames(intMembers)) { + this.swiftLines.push(` case ${this.renderIdentifier(name)} = ${raw}`); + } + this.swiftLines.push("}"); + this.swiftLines.push(`extension ${swiftEnumName}: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum {}`); + this.swiftLines.push(""); + return; + } + + this.diagnosticEngine.print( + "warning", + `Unsupported enum (only string or int enums are supported): ${enumName}`, + diagnosticNode + ); + this.swiftLines.push(`typealias ${swiftEnumName} = String`); + this.swiftLines.push(""); + } + + /** + * Visit a function declaration and render Swift code + * @param {ts.FunctionDeclaration} node - The function node + * @private + */ + visitFunctionDeclaration(node) { + if (!node.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; + + const parameters = signature.getParameters(); + const parameterNameMap = this.buildParameterNameMap(parameters); + const params = this.renderParameters(parameters, node); + const returnType = this.visitType(signature.getReturnType(), node); + const effects = this.renderEffects({ isAsync: false }); + const swiftFuncName = this.renderIdentifier(swiftName); + + this.emitDocComment(node, { parameterNameMap }); + this.swiftLines.push(`${annotation} func ${swiftFuncName}(${params}) ${effects} -> ${returnType}`); + this.swiftLines.push(""); + } + + /** + * Convert a JSDoc comment node content to plain text. + * @param {string | ts.NodeArray | undefined} comment + * @returns {string} + * @private + */ + renderJSDocText(comment) { + if (!comment) return ""; + if (typeof comment === "string") return comment; + let result = ""; + for (const part of comment) { + if (typeof part === "string") { + result += part; + continue; + } + // JSDocText/JSDocLink both have a `text` field + // https://github.com/microsoft/TypeScript/blob/main/src/compiler/types.ts + // @ts-ignore + if (typeof part.text === "string") { + // @ts-ignore + result += part.text; + continue; + } + if (typeof part.getText === "function") { + result += part.getText(); + } + } + return result; + } + + /** + * Split documentation text into lines suitable for DocC rendering. + * @param {string} text + * @returns {string[]} + * @private + */ + splitDocumentationText(text) { + if (!text) return []; + return text.split(/\r?\n/).map(line => line.trimEnd()); + } + + /** + * @param {string[]} lines + * @returns {boolean} + * @private + */ + hasMeaningfulLine(lines) { + return lines.some(line => line.trim().length > 0); + } + + /** + * Render Swift doc comments from a node's JSDoc, including parameter/return tags. + * @param {ts.Node} node + * @param {{ indent?: string, parameterNameMap?: Map }} options + * @private + */ + emitDocComment(node, options = {}) { + const indent = options.indent ?? ""; + const parameterNameMap = options.parameterNameMap ?? new Map(); + + /** @type {string[]} */ + const descriptionLines = []; + for (const doc of ts.getJSDocCommentsAndTags(node)) { + if (!ts.isJSDoc(doc)) continue; + const text = this.renderJSDocText(doc.comment); + if (text) { + descriptionLines.push(...this.splitDocumentationText(text)); + } + } + + /** @type {Array<{ name: string, lines: string[] }>} */ + const parameterDocs = []; + const supportsParameters = ( + ts.isFunctionLike(node) || + ts.isMethodSignature(node) || + ts.isCallSignatureDeclaration(node) || + ts.isConstructSignatureDeclaration(node) + ); + /** @type {ts.JSDocReturnTag | undefined} */ + let returnTag = undefined; + if (supportsParameters) { + for (const tag of ts.getJSDocTags(node)) { + if (ts.isJSDocParameterTag(tag)) { + const tsName = tag.name.getText(); + const name = parameterNameMap.get(tsName) ?? this.renderIdentifier(tsName); + const text = this.renderJSDocText(tag.comment); + const lines = this.splitDocumentationText(text); + parameterDocs.push({ name, lines }); + } else if (!returnTag && ts.isJSDocReturnTag(tag)) { + returnTag = tag; + } + } + } + + const returnLines = returnTag ? this.splitDocumentationText(this.renderJSDocText(returnTag.comment)) : []; + const hasDescription = this.hasMeaningfulLine(descriptionLines); + const hasParameters = parameterDocs.length > 0; + const hasReturns = returnTag !== undefined; + + if (!hasDescription && !hasParameters && !hasReturns) { + return; + } + + /** @type {string[]} */ + const docLines = []; + if (hasDescription) { + docLines.push(...descriptionLines); + } + + if (hasDescription && (hasParameters || hasReturns)) { + docLines.push(""); + } + + if (hasParameters) { + docLines.push("- Parameters:"); + for (const param of parameterDocs) { + const hasParamDescription = this.hasMeaningfulLine(param.lines); + const [firstParamLine, ...restParamLines] = param.lines; + if (hasParamDescription) { + docLines.push(` - ${param.name}: ${firstParamLine}`); + for (const line of restParamLines) { + docLines.push(` ${line}`); + } + } else { + docLines.push(` - ${param.name}:`); + } + } + } + + if (hasReturns) { + const hasReturnDescription = this.hasMeaningfulLine(returnLines); + const [firstReturnLine, ...restReturnLines] = returnLines; + if (hasReturnDescription) { + docLines.push(`- Returns: ${firstReturnLine}`); + for (const line of restReturnLines) { + docLines.push(` ${line}`); + } + } else { + docLines.push("- Returns:"); + } + } + + const prefix = `${indent}///`; + for (const line of docLines) { + if (line.length === 0) { + this.swiftLines.push(prefix); + } else { + this.swiftLines.push(`${prefix} ${line}`); + } + } + } + + /** + * Build a map from TypeScript parameter names to rendered Swift identifiers. + * @param {ts.Symbol[]} parameters + * @returns {Map} + * @private + */ + buildParameterNameMap(parameters) { + const map = new Map(); + for (const parameter of parameters) { + map.set(parameter.name, this.renderIdentifier(parameter.name)); + } + return map; + } + + /** @returns {string} */ + renderDefaultJSImportFromArgument() { + if (this.defaultImportFromGlobal) return "from: .global"; + return ""; + } + + /** + * Visit a property declaration and extract metadata + * @param {ts.PropertyDeclaration | ts.PropertySignature} node + * @returns {{ jsName: string, swiftName: string, type: string, isReadonly: boolean } | null} + */ + visitPropertyDecl(node) { + if (!node.name) return null; + /** @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; + return { jsName, swiftName, type: swiftType, isReadonly }; + } + + /** + * @param {ts.Symbol} symbol + * @param {ts.Node} node + * @returns {Parameter} + */ + visitSignatureParameter(symbol, node) { + const type = this.checker.getTypeOfSymbolAtLocation(symbol, node); + const swiftType = this.visitType(type, node); + return { name: symbol.name, type: swiftType }; + } + + /** + * Visit a class declaration and render Swift code + * @param {ts.ClassDeclaration} node + * @private + */ + visitClassDecl(node) { + if (!node.name) return; + + 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.emitDocComment(node, { indent: "" }); + this.swiftLines.push(`${annotation} struct ${className} {`); + + // Process members in declaration order + for (const member of node.members) { + if (ts.isPropertyDeclaration(member)) { + this.renderProperty(member); + } else if (ts.isMethodDeclaration(member)) { + this.renderMethod(member); + } else if (ts.isConstructorDeclaration(member)) { + this.renderConstructor(member); + } + } + + this.swiftLines.push("}"); + this.swiftLines.push(""); + } + + /** + * @param {ts.SymbolFlags} flags + * @returns {string[]} + */ + debugSymbolFlags(flags) { + const result = []; + for (const key in ts.SymbolFlags) { + const val = (ts.SymbolFlags)[key]; + if (typeof val === "number" && (flags & val) !== 0) { + result.push(key); + } + } + return result; + } + + /** + * @param {ts.TypeFlags} flags + * @returns {string[]} + */ + debugTypeFlags(flags) { + const result = []; + for (const key in ts.TypeFlags) { + const val = (ts.TypeFlags)[key]; + if (typeof val === "number" && (flags & val) !== 0) { + result.push(key); + } + } + return result; + } + + /** + * Visit a structured type (interface) and render Swift code + * @param {ts.Type} type + * @param {ts.Node} diagnosticNode + * @param {ts.Symbol[]} members + * @private + */ + visitStructuredType(type, diagnosticNode, members) { + const symbol = type.aliasSymbol ?? type.getSymbol(); + const name = type.aliasSymbol?.name ?? symbol?.name ?? this.checker.typeToString(type); + if (!name) return; + if (this.emittedStructuredTypeNames.has(name)) return; + this.emittedStructuredTypeNames.add(name); + + 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); + const docNode = type.aliasSymbol?.getDeclarations()?.[0] ?? symbol?.getDeclarations()?.[0] ?? diagnosticNode; + if (docNode) { + this.emitDocComment(docNode, { indent: "" }); + } + 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 }>} */ + const allDecls = []; + + const typeMembers = members ?? type.getProperties() ?? []; + for (const memberSymbol of typeMembers) { + for (const decl of memberSymbol.getDeclarations() ?? []) { + const sourceFile = decl.getSourceFile(); + const pos = sourceFile ? decl.getStart() : 0; + allDecls.push({ decl, symbol: memberSymbol, position: pos }); + } + } + + // Sort by position to preserve declaration order + allDecls.sort((a, b) => a.position - b.position); + + // Process declarations in order + for (const { decl, symbol } of allDecls) { + if (symbol.flags & ts.SymbolFlags.Property) { + if (ts.isPropertyDeclaration(decl) || ts.isPropertySignature(decl)) { + this.renderProperty(decl); + } else if (ts.isMethodSignature(decl)) { + this.renderMethodSignature(decl); + } + } else if (symbol.flags & ts.SymbolFlags.Method) { + if (ts.isMethodSignature(decl)) { + this.renderMethodSignature(decl); + } + } else if (symbol.flags & ts.SymbolFlags.Constructor) { + if (ts.isConstructorDeclaration(decl)) { + this.renderConstructor(decl); + } + } + } + + this.swiftLines.push("}"); + this.swiftLines.push(""); + } + + /** + * Convert TypeScript type to Swift type string + * @param {ts.Type} type - TypeScript type + * @param {ts.Node} node - Node + * @returns {string} Swift type string + * @private + */ + visitType(type, node) { + const typeArguments = this.getTypeArguments(type); + if (this.checker.isArrayType(type)) { + const typeArgs = this.checker.getTypeArguments(/** @type {ts.TypeReference} */ (type)); + if (typeArgs && typeArgs.length > 0) { + const elementType = this.visitType(typeArgs[0], node); + return `[${elementType}]`; + } + return "[JSObject]"; + } + + const recordType = this.convertRecordType(type, typeArguments, node); + if (recordType) { + return recordType; + } + + // Treat A and A as the same type + if (isTypeReference(type)) { + type = type.target; + } + const maybeProcessed = this.processedTypes.get(type); + if (maybeProcessed) { + return maybeProcessed; + } + /** + * @param {ts.Type} type + * @returns {string} + */ + const convert = (type) => { + // Handle nullable/undefined unions (e.g. T | null, T | undefined) + const isUnionType = (type.flags & ts.TypeFlags.Union) !== 0; + if (isUnionType) { + /** @type {ts.UnionType} */ + // @ts-ignore + const unionType = type; + const unionTypes = unionType.types; + const hasNull = unionTypes.some(t => (t.flags & ts.TypeFlags.Null) !== 0); + const hasUndefined = unionTypes.some(t => (t.flags & ts.TypeFlags.Undefined) !== 0); + const nonNullableTypes = unionTypes.filter( + t => (t.flags & ts.TypeFlags.Null) === 0 && (t.flags & ts.TypeFlags.Undefined) === 0 + ); + if (nonNullableTypes.length === 1 && (hasNull || hasUndefined)) { + const wrapped = this.visitType(nonNullableTypes[0], node); + if (hasNull && hasUndefined) { + return "JSObject"; + } + if (hasNull) { + return `Optional<${wrapped}>`; + } + return `JSUndefinedOr<${wrapped}>`; + } + } + + /** @type {Record} */ + const typeMap = { + "number": "Double", + "string": "String", + "boolean": "Bool", + "void": "Void", + "any": "JSValue", + "unknown": "JSValue", + "null": "Void", + "undefined": "Void", + "bigint": "Int", + "object": "JSObject", + "symbol": "JSObject", + "never": "Void", + "Promise": "JSPromise", + }; + const symbol = type.getSymbol() ?? type.aliasSymbol; + const typeString = symbol?.name ?? this.checker.typeToString(type); + if (typeMap[typeString]) { + return typeMap[typeString]; + } + if (symbol && (symbol.flags & ts.SymbolFlags.Enum) !== 0) { + const typeName = symbol.name; + this.seenTypes.set(type, node); + return this.renderTypeIdentifier(typeName); + } + + if (this.checker.isTupleType(type) || type.getCallSignatures().length > 0) { + return "JSObject"; + } + // "a" | "b" -> string + if (this.checker.isTypeAssignableTo(type, this.checker.getStringType())) { + return "String"; + } + if (type.isTypeParameter()) { + return "JSObject"; + } + + const typeName = this.deriveTypeName(type); + if (!typeName) { + this.diagnosticEngine.print("warning", `Unknown non-nominal type: ${typeString}`, node); + return "JSObject"; + } + this.seenTypes.set(type, node); + return this.renderTypeIdentifier(typeName); + } + const swiftType = convert(type); + this.processedTypes.set(type, swiftType); + return swiftType; + } + + /** + * Convert a `Record` TypeScript type into a Swift dictionary type. + * Falls back to `JSObject` when keys are not string-compatible or type arguments are missing. + * @param {ts.Type} type + * @param {readonly ts.Type[]} typeArguments + * @param {ts.Node} node + * @returns {string | null} + * @private + */ + convertRecordType(type, typeArguments, node) { + const symbol = type.aliasSymbol ?? type.getSymbol(); + if (!symbol || symbol.name !== "Record") { + return null; + } + if (typeArguments.length !== 2) { + this.diagnosticEngine.print("warning", "Record expects two type arguments", node); + return "JSObject"; + } + const [keyType, valueType] = typeArguments; + const stringType = this.checker.getStringType(); + if (!this.checker.isTypeAssignableTo(keyType, stringType)) { + this.diagnosticEngine.print( + "warning", + `Record key type must be assignable to string: ${this.checker.typeToString(keyType)}`, + node + ); + return "JSObject"; + } + + const valueSwiftType = this.visitType(valueType, node); + return `[String: ${valueSwiftType}]`; + } + + /** + * Retrieve type arguments for a given type, including type alias instantiations. + * @param {ts.Type} type + * @returns {readonly ts.Type[]} + * @private + */ + getTypeArguments(type) { + if (isTypeReference(type)) { + return this.checker.getTypeArguments(type); + } + // Non-TypeReference alias instantiations store type arguments separately. + // @ts-ignore: `aliasTypeArguments` is intentionally accessed for alias instantiations. + return type.aliasTypeArguments ?? []; + } + + /** + * Derive the type name from a type + * @param {ts.Type} type - TypeScript type + * @returns {string | undefined} Type name + * @private + */ + deriveTypeName(type) { + const aliasSymbol = type.aliasSymbol; + if (aliasSymbol) { + return aliasSymbol.name; + } + const typeSymbol = type.getSymbol(); + if (typeSymbol) { + return typeSymbol.name; + } + return undefined; + } + + /** + * Render a property declaration + * @param {ts.PropertyDeclaration | ts.PropertySignature} node + * @private + */ + renderProperty(node) { + const property = this.visitPropertyDecl(node); + if (!property) return; + + const type = property.type; + 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.emitDocComment(node, { indent: " " }); + this.swiftLines.push(` ${getterAnnotation} var ${swiftName}: ${type}`); + + // Render setter if not readonly + if (!property.isReadonly) { + 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 })}`); + } + } + + /** + * Render a method declaration + * @param {ts.MethodDeclaration | ts.MethodSignature} node + * @private + */ + renderMethod(node) { + if (!node.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; + + const parameters = signature.getParameters(); + const parameterNameMap = this.buildParameterNameMap(parameters); + const params = this.renderParameters(parameters, node); + const returnType = this.visitType(signature.getReturnType(), node); + const effects = this.renderEffects({ isAsync: false }); + const swiftMethodName = this.renderIdentifier(swiftName); + const isStatic = node.modifiers?.some( + (modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword + ) ?? false; + const staticKeyword = isStatic ? "static " : ""; + + this.emitDocComment(node, { indent: " ", parameterNameMap }); + this.swiftLines.push(` ${annotation} ${staticKeyword}func ${swiftMethodName}(${params}) ${effects} -> ${returnType}`); + } + + /** + * Render a method signature (from interface) + * @param {ts.MethodSignature} node + * @private + */ + renderMethodSignature(node) { + this.renderMethod(node); + } + + /** + * Render a constructor declaration + * @param {ts.ConstructorDeclaration} node + * @private + */ + renderConstructor(node) { + const signature = this.checker.getSignatureFromDeclaration(node); + if (!signature) return; + + const parameters = signature.getParameters(); + const parameterNameMap = this.buildParameterNameMap(parameters); + const params = this.renderParameters(parameters, node); + const effects = this.renderEffects({ isAsync: false }); + this.emitDocComment(node, { indent: " ", parameterNameMap }); + this.swiftLines.push(` @JSFunction init(${params}) ${effects}`); + } + + /** + * Render function parameters + * @param {ts.Symbol[]} parameters + * @param {ts.Node} node + * @returns {string} + * @private + */ + renderParameters(parameters, node) { + const params = []; + for (const p of parameters) { + const param = this.visitSignatureParameter(p, node); + const paramName = this.renderIdentifier(p.name); + const type = param.type; + params.push(`_ ${paramName}: ${type}`); + } + return params.join(", "); + } + + /** + * Render effects (async/throws) + * @param {{ isAsync: boolean }} effects + * @returns {string} + * @private + */ + renderEffects(effects) { + const parts = []; + if (effects?.isAsync) { + parts.push("async"); + } + parts.push("throws(JSException)"); + return parts.join(" "); + } + + /** + * Render identifier with backticks if needed + * @param {string} name + * @returns {string} + * @private + */ + renderIdentifier(name) { + if (!name) return name; + if (!isValidSwiftDeclName(name) || isSwiftKeyword(name)) { + return `\`${name}\``; + } + return name; + } +} + + +const SWIFT_KEYWORDS = new Set([ + "associatedtype", "class", "deinit", "enum", "extension", "fileprivate", + "func", "import", "init", "inout", "internal", "let", "open", "operator", + "private", "protocol", "public", "static", "struct", "subscript", "typealias", + "var", "break", "case", "continue", "default", "defer", "do", "else", + "fallthrough", "for", "guard", "if", "in", "repeat", "return", "switch", + "where", "while", "as", "Any", "catch", "false", "is", "nil", "rethrows", + "super", "self", "Self", "throw", "throws", "true", "try", + "prefix", "postfix", "infix" // Contextual keywords for operator declarations +]); + +/** + * @param {string} name + * @returns {boolean} + */ +function isSwiftKeyword(name) { + return SWIFT_KEYWORDS.has(name); +} + +/** + * @param {ts.Type} type + * @returns {type is ts.ObjectType} + */ +function isObjectType(type) { + // @ts-ignore + return typeof type.objectFlags === "number"; +} + +/** + * + * @param {ts.Type} type + * @returns {type is ts.TypeReference} + */ +function isTypeReference(type) { + return ( + isObjectType(type) && + (type.objectFlags & ts.ObjectFlags.Reference) !== 0 + ); +} + +/** + * Check if a declaration name is valid for Swift generation + * @param {string} name - Declaration name to check + * @returns {boolean} True if the name is valid for Swift + * @private + */ +export function isValidSwiftDeclName(name) { + // https://docs.swift.org/swift-book/documentation/the-swift-programming-language/lexicalstructure/ + const swiftIdentifierRegex = /^[_\p{ID_Start}][\p{ID_Continue}\u{200C}\u{200D}]*$/u; + return swiftIdentifierRegex.test(name); +} + +/** + * Convert an arbitrary string into a valid Swift identifier. + * @param {string} name + * @param {{ emptyFallback?: string }} options + * @returns {string} + */ +function makeValidSwiftIdentifier(name, options = {}) { + const emptyFallback = options.emptyFallback ?? "_"; + let result = ""; + for (const ch of name) { + const isIdentifierChar = /^[_\p{ID_Continue}\u{200C}\u{200D}]$/u.test(ch); + result += isIdentifierChar ? ch : "_"; + } + if (!result) result = emptyFallback; + if (!/^[_\p{ID_Start}]$/u.test(result[0])) { + result = "_" + result; + } + if (!isValidSwiftDeclName(result)) { + result = result.replace(/[^_\p{ID_Continue}\u{200C}\u{200D}]/gu, "_"); + if (!result) result = emptyFallback; + if (!/^[_\p{ID_Start}]$/u.test(result[0])) { + result = "_" + result; + } + } + if (isSwiftKeyword(result)) { + result = result + "_"; + } + return result; +} diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/__snapshots__/ts2swift.test.js.snap b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/__snapshots__/ts2swift.test.js.snap new file mode 100644 index 000000000..85d1da0de --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/__snapshots__/ts2swift.test.js.snap @@ -0,0 +1,567 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`ts2swift > snapshots Swift output for ArrayParameter.d.ts > ArrayParameter 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func processNumbers(_ values: [Double]) throws(JSException) -> Void + +@JSFunction func getNumbers() throws(JSException) -> [Double] + +@JSFunction func transformNumbers(_ values: [Double]) throws(JSException) -> [Double] + +@JSFunction func processStrings(_ values: [String]) throws(JSException) -> [String] + +@JSFunction func processBooleans(_ values: [Bool]) throws(JSException) -> [Bool] + +@JSFunction func processArraySyntax(_ values: [Double]) throws(JSException) -> [Double] +" +`; + +exports[`ts2swift > snapshots Swift output for Async.d.ts > Async 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func asyncReturnVoid() throws(JSException) -> JSPromise + +@JSFunction func asyncRoundTripInt(_ v: Double) throws(JSException) -> JSPromise + +@JSFunction func asyncRoundTripString(_ v: String) throws(JSException) -> JSPromise + +@JSFunction func asyncRoundTripBool(_ v: Bool) throws(JSException) -> JSPromise + +@JSFunction func asyncRoundTripFloat(_ v: Double) throws(JSException) -> JSPromise + +@JSFunction func asyncRoundTripDouble(_ v: Double) throws(JSException) -> JSPromise + +@JSFunction func asyncRoundTripJSObject(_ v: JSValue) throws(JSException) -> JSPromise +" +`; + +exports[`ts2swift > snapshots Swift output for Documentation.d.ts > Documentation 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +/// Return a greeting for a user. +/// +/// - Parameters: +/// - name: The user's name. +/// - Returns: The greeting message. +@JSFunction func greet(_ name: String) throws(JSException) -> String + +@JSFunction func origin() throws(JSException) -> Point + +/// Represents a 2D point. +@JSClass struct Point { + /// The horizontal position. + @JSGetter var x: Double + @JSSetter func setX(_ value: Double) throws(JSException) + /// Translate the point. + /// + /// - Parameters: + /// - dx: Delta to apply on x. + /// - dy: Delta to apply on y. + /// - Returns: The moved point. + @JSFunction func translate(_ dx: Double, _ dy: Double) throws(JSException) -> Point +} + +/// Move a point by the given delta. +/// +/// - Parameters: +/// - point: The point to move. +/// - dx: Delta to apply on x. +/// - dy: Delta to apply on y. +@JSFunction func translatePoint(_ point: Point, _ dx: Double, _ dy: Double) throws(JSException) -> Point + +/// A greeter that keeps the target name. +@JSClass struct Greeter { + /// Create a greeter. + /// + /// - Parameters: + /// - name: Name to greet. + @JSFunction init(_ name: String) throws(JSException) + /// The configured name. + @JSGetter var targetName: String + /// Say hello. + /// + /// - Returns: Greeting message. + @JSFunction func greet() throws(JSException) -> String +} +" +`; + +exports[`ts2swift > snapshots Swift output for Interface.d.ts > Interface 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func returnAnimatable() throws(JSException) -> Animatable + +@JSClass struct Animatable { + @JSFunction func animate(_ keyframes: JSValue, _ options: JSValue) throws(JSException) -> JSValue + @JSFunction func getAnimations(_ options: JSValue) throws(JSException) -> JSValue +} +" +`; + +exports[`ts2swift > snapshots Swift output for InvalidPropertyNames.d.ts > InvalidPropertyNames 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func createArrayBuffer() throws(JSException) -> ArrayBufferLike + +@JSClass struct ArrayBufferLike { + @JSGetter var byteLength: Double + @JSFunction func slice(_ begin: Double, _ end: Double) throws(JSException) -> ArrayBufferLike +} + +@JSFunction func createWeirdObject() throws(JSException) -> WeirdNaming + +@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 +" +`; + +exports[`ts2swift > snapshots Swift output for MultipleImportedTypes.d.ts > MultipleImportedTypes 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func createDatabaseConnection(_ config: JSValue) throws(JSException) -> DatabaseConnection + +@JSClass struct DatabaseConnection { + @JSFunction func connect(_ url: String) throws(JSException) -> Void + @JSFunction func execute(_ query: String) throws(JSException) -> JSValue + @JSGetter var isConnected: Bool + @JSGetter var connectionTimeout: Double + @JSSetter func setConnectionTimeout(_ value: Double) throws(JSException) +} + +@JSFunction func createLogger(_ level: String) throws(JSException) -> Logger + +@JSClass struct Logger { + @JSFunction func log(_ message: String) throws(JSException) -> Void + @JSFunction func error(_ message: String, _ error: JSValue) throws(JSException) -> Void + @JSGetter var level: String +} + +@JSFunction func getConfigManager() throws(JSException) -> ConfigManager + +@JSClass struct ConfigManager { + @JSFunction func get(_ key: String) throws(JSException) -> JSValue + @JSFunction func set(_ key: String, _ value: JSValue) throws(JSException) -> Void + @JSGetter var configPath: String +} +" +`; + +exports[`ts2swift > snapshots Swift output for ObjectLikeTypes.d.ts > ObjectLikeTypes 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func acceptObject(_ v: JSObject) throws(JSException) -> Void +" +`; + +exports[`ts2swift > snapshots Swift output for OptionalNullUndefined.d.ts > OptionalNullUndefined 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func roundTripNumberNull(_ value: Optional) throws(JSException) -> Optional + +@JSFunction func roundTripNumberUndefined(_ value: JSUndefinedOr) throws(JSException) -> JSUndefinedOr + +@JSFunction func roundTripStringNull(_ value: Optional) throws(JSException) -> Optional + +@JSFunction func roundTripStringUndefined(_ value: JSUndefinedOr) throws(JSException) -> JSUndefinedOr + +@JSFunction func roundTripBooleanNull(_ value: JSObject) throws(JSException) -> JSObject + +@JSFunction func roundTripBooleanUndefined(_ value: JSObject) throws(JSException) -> JSObject + +@JSFunction func optionalNumberParamNull(_ x: Double, _ maybe: Optional) throws(JSException) -> Double + +@JSFunction func optionalNumberParamUndefined(_ x: Double, _ maybe: JSUndefinedOr) throws(JSException) -> Double + +@JSFunction func roundTripMyInterfaceNull(_ value: Optional) throws(JSException) -> Optional + +@JSClass struct MyInterface { +} + +@JSFunction func roundTripMyInterfaceUndefined(_ value: JSUndefinedOr) throws(JSException) -> JSUndefinedOr + +@JSClass struct WithOptionalFields { + @JSGetter var valueOrNull: Optional + @JSSetter func setValueOrNull(_ value: Optional) throws(JSException) + @JSGetter var valueOrUndefined: JSUndefinedOr + @JSSetter func setValueOrUndefined(_ value: JSUndefinedOr) throws(JSException) +} +" +`; + +exports[`ts2swift > snapshots Swift output for PrimitiveParameters.d.ts > PrimitiveParameters 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func check(_ a: Double, _ b: Bool) throws(JSException) -> Void +" +`; + +exports[`ts2swift > snapshots Swift output for PrimitiveReturn.d.ts > PrimitiveReturn 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func checkNumber() throws(JSException) -> Double + +@JSFunction func checkBoolean() throws(JSException) -> Bool +" +`; + +exports[`ts2swift > snapshots Swift output for ReExportFrom.d.ts > ReExportFrom 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func jsRoundTripNumber(_ v: Double) throws(JSException) -> Double + +@JSClass struct JsGreeter { + @JSFunction init(_ name: String) throws(JSException) + @JSFunction func greet() throws(JSException) -> String +} +" +`; + +exports[`ts2swift > snapshots Swift output for RecordDictionary.d.ts > RecordDictionary 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func takeRecord(_ value: [String: Double]) throws(JSException) -> Void + +@JSFunction func returnRecord() throws(JSException) -> [String: String] + +@JSFunction func optionalRecord(_ value: Optional<[String: Bool]>) throws(JSException) -> Optional<[String: Bool]> + +@JSFunction func nestedRecord(_ value: [String: [String: Double]]) throws(JSException) -> [String: [String: Double]] + +@JSFunction func recordWithArrayValues(_ values: [String: [Double]]) throws(JSException) -> [String: [Double]] + +@JSFunction func recordWithObjects(_ values: [String: Optional]) throws(JSException) -> [String: Optional] + +@JSClass struct Box { + @JSGetter var value: Double + @JSSetter func setValue(_ value: Double) throws(JSException) +} + +@JSFunction func unsupportedKeyRecord(_ values: JSObject) throws(JSException) -> Void +" +`; + +exports[`ts2swift > snapshots Swift output for StringEnum.d.ts > StringEnum 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +enum FeatureFlag: String { + case foo = "foo" + case bar = "bar" +} +extension FeatureFlag: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum {} + +@JSFunction func takesFeatureFlag(_ flag: FeatureFlag) throws(JSException) -> Void + +@JSFunction func returnsFeatureFlag() throws(JSException) -> FeatureFlag +" +`; + +exports[`ts2swift > snapshots Swift output for StringParameter.d.ts > StringParameter 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func checkString(_ a: String) throws(JSException) -> Void + +@JSFunction func checkStringWithLength(_ a: String, _ b: Double) throws(JSException) -> Void +" +`; + +exports[`ts2swift > snapshots Swift output for StringReturn.d.ts > StringReturn 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func checkString() throws(JSException) -> String +" +`; + +exports[`ts2swift > snapshots Swift output for TS2SkeletonLike.d.ts > TS2SkeletonLike 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func createTS2Skeleton() throws(JSException) -> TypeScriptProcessor + +@JSClass struct TypeScriptProcessor { + @JSFunction func convert(_ ts: String) throws(JSException) -> String + @JSFunction func validate(_ ts: String) throws(JSException) -> Bool + @JSGetter var version: String +} + +@JSFunction func createCodeGenerator(_ format: String) throws(JSException) -> CodeGenerator + +@JSClass struct CodeGenerator { + @JSFunction func generate(_ input: JSValue) throws(JSException) -> String + @JSGetter var outputFormat: String +} +" +`; + +exports[`ts2swift > snapshots Swift output for TypeAlias.d.ts > TypeAlias 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func checkSimple(_ a: Double) throws(JSException) -> Void +" +`; + +exports[`ts2swift > snapshots Swift output for TypeAliasObject.d.ts > TypeAliasObject 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func console() throws(JSException) -> Console + +/// Console from the environment. +@JSClass struct Console { + /// Log a message. + @JSFunction func log(_ message: String) throws(JSException) -> Void +} +" +`; + +exports[`ts2swift > snapshots Swift output for TypeScriptClass.d.ts > TypeScriptClass 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSClass struct Greeter { + @JSGetter var name: String + @JSSetter func setName(_ value: String) throws(JSException) + @JSGetter var age: Double + @JSFunction init(_ name: String) throws(JSException) + @JSFunction func greet() throws(JSException) -> String + @JSFunction func changeName(_ name: String) throws(JSException) -> Void + @JSFunction static func staticMethod(_ p1: Double, _ p2: String) throws(JSException) -> String +} +" +`; + +exports[`ts2swift > snapshots Swift output for VoidParameterVoidReturn.d.ts > VoidParameterVoidReturn 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func check() throws(JSException) -> Void +" +`; + +exports[`ts2swift > snapshots Swift output for WebIDLDOMDocs.d.ts > WebIDLDOMDocs 1`] = ` +"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// \`swift package bridge-js\`. + +@_spi(BridgeJS) import JavaScriptKit + +/// [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document) +@JSGetter var document: Document + +/// A simple Document subset with WebIDL-derived comments. +@JSClass struct Document { + /// Creates an instance of the element for the specified tag. + /// + /// - Parameters: + /// - tagName: The name of an element. + /// + /// [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createElement) + @JSFunction func createElement(_ tagName: String, _ options: JSUndefinedOr) throws(JSException) -> Element + /// Returns an element with namespace namespace. Its namespace prefix will be everything before ":" (U+003E) in qualifiedName or null. Its local name will be everything after ":" (U+003E) in qualifiedName or qualifiedName. + /// + /// If localName does not match the Name production an "InvalidCharacterError" DOMException will be thrown. + /// + /// If one of the following conditions is true a "NamespaceError" DOMException will be thrown: + /// + /// localName does not match the QName production. + /// Namespace prefix is not null and namespace is the empty string. + /// Namespace prefix is "xml" and namespace is not the XML namespace. + /// qualifiedName or namespace prefix is "xmlns" and namespace is not the XMLNS namespace. + /// namespace is the XMLNS namespace and neither qualifiedName nor namespace prefix is "xmlns". + /// + /// When supplied, options's is can be used to create a customized built-in element. + /// + /// [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createElementNS) + @JSFunction func createElementNS(_ namespaceURI: Optional, _ qualifiedName: String, _ options: JSObject) throws(JSException) -> Element + /// Creates a TreeWalker object. + /// + /// - Parameters: + /// - root: The root element or node to start traversing on. + /// - whatToShow: The type of nodes or elements to appear in the node list + /// - filter: A custom NodeFilter function to use. For more information, see filter. Use null for no filter. + /// - Returns: The created TreeWalker. + /// + /// [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createTreeWalker) + @JSFunction func createTreeWalker(_ root: Node, _ whatToShow: JSUndefinedOr, _ filter: JSUndefinedOr) throws(JSException) -> TreeWalker +} + +@JSClass struct ElementCreationOptions { + @JSGetter var \`is\`: JSUndefinedOr + @JSSetter func setIs(_ value: JSUndefinedOr) throws(JSException) +} + +@JSClass struct Element { + /// [MDN Reference](https://developer.mozilla.org/docs/Web/API/Node/textContent) + @JSGetter var textContent: Optional + @JSSetter func setTextContent(_ value: Optional) throws(JSException) + /// Returns a copy of node. If deep is true, the copy also includes the node's descendants. + /// + /// [MDN Reference](https://developer.mozilla.org/docs/Web/API/Node/cloneNode) + @JSFunction func cloneNode(_ subtree: JSObject) throws(JSException) -> Node +} + +/// Minimal stubs to mirror lib.dom.d.ts documentation converted from WebIDL. +@JSClass struct Node { + /// [MDN Reference](https://developer.mozilla.org/docs/Web/API/Node/textContent) + @JSGetter var textContent: Optional + @JSSetter func setTextContent(_ value: Optional) throws(JSException) + /// Returns a copy of node. If deep is true, the copy also includes the node's descendants. + /// + /// [MDN Reference](https://developer.mozilla.org/docs/Web/API/Node/cloneNode) + @JSFunction func cloneNode(_ subtree: JSObject) throws(JSException) -> Node +} + +@JSClass struct TreeWalker { + /// [MDN Reference](https://developer.mozilla.org/docs/Web/API/TreeWalker/currentNode) + @JSGetter var currentNode: Node + @JSSetter func setCurrentNode(_ value: Node) throws(JSException) + /// Moves the currentNode to the next visible node in the document order. + /// + /// [MDN Reference](https://developer.mozilla.org/docs/Web/API/TreeWalker/nextNode) + @JSFunction func nextNode() throws(JSException) -> Optional +} +" +`; diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/ArrayParameter.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/ArrayParameter.d.ts new file mode 100644 index 000000000..b5a099388 --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/ArrayParameter.d.ts @@ -0,0 +1,17 @@ +// Array as parameter +export function processNumbers(values: number[]): void; + +// Array as return value +export function getNumbers(): number[]; + +// Array as both parameter and return value +export function transformNumbers(values: number[]): number[]; + +// String arrays +export function processStrings(values: string[]): string[]; + +// Boolean arrays +export function processBooleans(values: boolean[]): boolean[]; + +// Using Array syntax +export function processArraySyntax(values: Array): Array; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Async.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/Async.d.ts similarity index 100% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Async.d.ts rename to Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/Async.d.ts diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/Documentation.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/Documentation.d.ts new file mode 100644 index 000000000..90ba064bb --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/Documentation.d.ts @@ -0,0 +1,56 @@ +/** + * Return a greeting for a user. + * @param name The user's name. + * @returns The greeting message. + */ +export function greet(name: string): string; + +/** + * Represents a 2D point. + */ +export interface Point { + /** + * The horizontal position. + */ + x: number; + + /** + * Translate the point. + * @param dx Delta to apply on x. + * @param dy Delta to apply on y. + * @returns The moved point. + */ + translate(dx: number, dy: number): Point; +} + +export function origin(): Point; + +/** + * Move a point by the given delta. + * @param point The point to move. + * @param dx Delta to apply on x. + * @param dy Delta to apply on y. + */ +export function translatePoint(point: Point, dx: number, dy: number): Point; + +/** + * A greeter that keeps the target name. + */ +export class Greeter { + /** + * Create a greeter. + * @param name Name to greet. + */ + constructor(name: string); + + /** + * The configured name. + */ + readonly targetName: string; + + /** + * Say hello. + * @returns Greeting message. + */ + greet(): string; +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Interface.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/Interface.d.ts similarity index 100% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Interface.d.ts rename to Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/Interface.d.ts diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/InvalidPropertyNames.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/InvalidPropertyNames.d.ts new file mode 100644 index 000000000..b9d3722b8 --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/InvalidPropertyNames.d.ts @@ -0,0 +1,30 @@ +interface ArrayBufferLike { + readonly byteLength: number; + readonly [Symbol.toStringTag]: string; + slice(begin: number, end: number): ArrayBufferLike; +} + +interface WeirdNaming { + normalProperty: string; + "property-with-dashes": number; + "123invalidStart": boolean; + "property with spaces": string; + readonly [Symbol.species]: any; + [Symbol.asyncIterator](): AsyncIterator; + "@specialChar": number; + "constructor": string; // This should be valid + for: string; + Any: string; + as(): void; + "try"(): void; +} + +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/MultipleImportedTypes.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/MultipleImportedTypes.d.ts similarity index 100% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MultipleImportedTypes.d.ts rename to Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/MultipleImportedTypes.d.ts diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/ObjectLikeTypes.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/ObjectLikeTypes.d.ts new file mode 100644 index 000000000..d605048cd --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/ObjectLikeTypes.d.ts @@ -0,0 +1 @@ +export function acceptObject(v: object): void; diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/OptionalNullUndefined.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/OptionalNullUndefined.d.ts new file mode 100644 index 000000000..8b64528d9 --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/OptionalNullUndefined.d.ts @@ -0,0 +1,20 @@ +export function roundTripNumberNull(value: number | null): number | null; +export function roundTripNumberUndefined(value: number | undefined): number | undefined; + +export function roundTripStringNull(value: string | null): string | null; +export function roundTripStringUndefined(value: string | undefined): string | undefined; + +export function roundTripBooleanNull(value: boolean | null): boolean | null; +export function roundTripBooleanUndefined(value: boolean | undefined): boolean | undefined; + +export function optionalNumberParamNull(x: number, maybe: number | null): number; +export function optionalNumberParamUndefined(x: number, maybe: number | undefined): number; + +export interface MyInterface {} +export function roundTripMyInterfaceNull(value: MyInterface | null): MyInterface | null; +export function roundTripMyInterfaceUndefined(value: MyInterface | undefined): MyInterface | undefined; + +export class WithOptionalFields { + valueOrNull: MyInterface | null; + valueOrUndefined: MyInterface | undefined; +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveParameters.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/PrimitiveParameters.d.ts similarity index 100% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveParameters.d.ts rename to Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/PrimitiveParameters.d.ts diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveReturn.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/PrimitiveReturn.d.ts similarity index 100% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveReturn.d.ts rename to Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/PrimitiveReturn.d.ts diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/ReExportFrom.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/ReExportFrom.d.ts new file mode 100644 index 000000000..0614f14c3 --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/ReExportFrom.d.ts @@ -0,0 +1,2 @@ +export { jsRoundTripNumber } from "./Support/ReExportTarget" +export { JsGreeter } from "./Support/ReExportTarget" diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/RecordDictionary.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/RecordDictionary.d.ts new file mode 100644 index 000000000..cfaf5f309 --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/RecordDictionary.d.ts @@ -0,0 +1,17 @@ +export interface Box { + value: number; +} + +export function takeRecord(value: Record): void; + +export function returnRecord(): Record; + +export function optionalRecord(value: Record | null): Record | null; + +export function nestedRecord(value: Record>): Record>; + +export function recordWithArrayValues(values: Record): Record; + +export function recordWithObjects(values: Record): Record; + +export function unsupportedKeyRecord(values: Record): void; diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/StringEnum.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/StringEnum.d.ts new file mode 100644 index 000000000..10f6dd819 --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/StringEnum.d.ts @@ -0,0 +1,8 @@ +export enum FeatureFlag { + foo = "foo", + bar = "bar", +} + +export function takesFeatureFlag(flag: FeatureFlag): void + +export function returnsFeatureFlag(): FeatureFlag diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringParameter.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/StringParameter.d.ts similarity index 100% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringParameter.d.ts rename to Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/StringParameter.d.ts diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringReturn.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/StringReturn.d.ts similarity index 100% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringReturn.d.ts rename to Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/StringReturn.d.ts diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/Support/ReExportTarget.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/Support/ReExportTarget.d.ts new file mode 100644 index 000000000..1867b1979 --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/Support/ReExportTarget.d.ts @@ -0,0 +1,7 @@ +export function jsRoundTripNumber(v: number): number + +export class JsGreeter { + constructor(name: string); + greet(): string; +} + diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/TS2SkeletonLike.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/TS2SkeletonLike.d.ts similarity index 100% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/TS2SkeletonLike.d.ts rename to Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/TS2SkeletonLike.d.ts diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/TypeAlias.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/TypeAlias.d.ts similarity index 100% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/TypeAlias.d.ts rename to Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/TypeAlias.d.ts diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/TypeAliasObject.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/TypeAliasObject.d.ts new file mode 100644 index 000000000..55ffdfa3a --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/TypeAliasObject.d.ts @@ -0,0 +1,11 @@ +/** + * Console from the environment. + */ +export type Console = { + /** + * Log a message. + */ + log(message: string): void; +}; + +export function console(): Console; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/TypeScriptClass.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/TypeScriptClass.d.ts similarity index 73% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/TypeScriptClass.d.ts rename to Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/TypeScriptClass.d.ts index 074772f24..0745de1f9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/TypeScriptClass.d.ts +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/TypeScriptClass.d.ts @@ -4,4 +4,6 @@ export class Greeter { constructor(name: string); greet(): string; changeName(name: string): void; + + static staticMethod(p1: number, p2: string): string; } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/VoidParameterVoidReturn.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/VoidParameterVoidReturn.d.ts similarity index 100% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/VoidParameterVoidReturn.d.ts rename to Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/VoidParameterVoidReturn.d.ts diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/WebIDLDOMDocs.d.ts b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/WebIDLDOMDocs.d.ts new file mode 100644 index 000000000..ace4011a4 --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/WebIDLDOMDocs.d.ts @@ -0,0 +1,81 @@ +/** + * Minimal stubs to mirror lib.dom.d.ts documentation converted from WebIDL. + */ + +interface Node { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Node/textContent) */ + textContent: string | null; + /** + * Returns a copy of node. If deep is true, the copy also includes the node's descendants. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Node/cloneNode) + */ + cloneNode(subtree?: boolean): Node; +} + +interface Element extends Node {} +type HTMLElement = Element; +type SVGElement = Element; +type MathMLElement = Element; +type DocumentFragment = Node; + +interface ElementCreationOptions { + is?: string; +} + +/** + * A simple Document subset with WebIDL-derived comments. + */ +interface Document { + /** + * Creates an instance of the element for the specified tag. + * @param tagName The name of an element. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createElement) + */ + createElement(tagName: string, options?: ElementCreationOptions): HTMLElement; + + /** + * Returns an element with namespace namespace. Its namespace prefix will be everything before ":" (U+003E) in qualifiedName or null. Its local name will be everything after ":" (U+003E) in qualifiedName or qualifiedName. + * + * If localName does not match the Name production an "InvalidCharacterError" DOMException will be thrown. + * + * If one of the following conditions is true a "NamespaceError" DOMException will be thrown: + * + * localName does not match the QName production. + * Namespace prefix is not null and namespace is the empty string. + * Namespace prefix is "xml" and namespace is not the XML namespace. + * qualifiedName or namespace prefix is "xmlns" and namespace is not the XMLNS namespace. + * namespace is the XMLNS namespace and neither qualifiedName nor namespace prefix is "xmlns". + * + * When supplied, options's is can be used to create a customized built-in element. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createElementNS) + */ + createElementNS(namespaceURI: string | null, qualifiedName: string, options?: string | ElementCreationOptions): Element; + + /** + * Creates a TreeWalker object. + * @param root The root element or node to start traversing on. + * @param whatToShow The type of nodes or elements to appear in the node list + * @param filter A custom NodeFilter function to use. For more information, see filter. Use null for no filter. + * @returns The created TreeWalker. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createTreeWalker) + */ + createTreeWalker(root: Node, whatToShow?: number, filter?: (node: Node) => number | null): TreeWalker; +} + +interface TreeWalker { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/TreeWalker/currentNode) */ + currentNode: Node; + /** + * Moves the currentNode to the next visible node in the document order. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/TreeWalker/nextNode) + */ + nextNode(): Node | null; +} + +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document) */ +export const document: Document; diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/tsconfig.json b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/tsconfig.json new file mode 100644 index 000000000..86e2ba175 --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/fixtures/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "es2017", + "module": "commonjs", + "lib": ["es2017"], + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/ts2swift.test.js b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/ts2swift.test.js new file mode 100644 index 000000000..8ca1df7c9 --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/ts2swift.test.js @@ -0,0 +1,41 @@ +// @ts-check +import { describe, it, expect } from 'vitest'; +import { readdirSync } from 'fs'; +import { fileURLToPath } from 'url'; +import path from 'path'; +import { run } from '../src/cli.js'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +/** Path to BridgeJSToolTests/Inputs/TypeScript (.d.ts fixtures and tsconfig). */ +const inputsDir = path.resolve(__dirname, 'fixtures'); +const tsconfigPath = path.join(inputsDir, 'tsconfig.json'); + +function runTs2Swift(dtsPath) { + return run([dtsPath], { tsconfigPath, logLevel: 'error' }); +} + +function collectDtsInputs() { + const entries = readdirSync(inputsDir, { withFileTypes: true }); + return entries + .filter((e) => e.isFile() && e.name.endsWith('.d.ts')) + .map((e) => e.name) + .sort(); +} + +describe('ts2swift', () => { + const dtsFiles = collectDtsInputs(); + if (dtsFiles.length === 0) { + it.skip('no .d.ts fixtures found in BridgeJSToolTests/Inputs', () => {}); + return; + } + + for (const dtsFile of dtsFiles) { + it(`snapshots Swift output for ${dtsFile}`, () => { + const dtsPath = path.join(inputsDir, dtsFile); + const swiftOutput = runTs2Swift(dtsPath); + const name = dtsFile.replace(/\.d\.ts$/, ''); + expect(swiftOutput).toMatchSnapshot(name); + }); + } +}); diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/tsconfig.json b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/tsconfig.json new file mode 100644 index 000000000..ed3dcf4bf --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "strict": true, + "allowJs": true, + "skipLibCheck": true, + "noEmit": true, + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "nodenext" + }, + "include": [ + "src/*.js" + ] +} diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/vitest.config.js b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/vitest.config.js new file mode 100644 index 000000000..d5d33a7e1 --- /dev/null +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/vitest.config.js @@ -0,0 +1,9 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + snapshotFormat: { + escapeString: false, + }, + }, +}); diff --git a/Plugins/BridgeJS/Sources/TS2Skeleton/TS2Skeleton.swift b/Plugins/BridgeJS/Sources/TS2Swift/TS2Swift.swift similarity index 60% rename from Plugins/BridgeJS/Sources/TS2Skeleton/TS2Skeleton.swift rename to Plugins/BridgeJS/Sources/TS2Swift/TS2Swift.swift index c7725faf8..6337dcf27 100644 --- a/Plugins/BridgeJS/Sources/TS2Skeleton/TS2Skeleton.swift +++ b/Plugins/BridgeJS/Sources/TS2Swift/TS2Swift.swift @@ -1,4 +1,3 @@ -@preconcurrency import class Foundation.JSONDecoder @preconcurrency import class Foundation.Process @preconcurrency import class Foundation.Pipe @preconcurrency import class Foundation.ProcessInfo @@ -11,6 +10,8 @@ @preconcurrency import var Foundation.SIGTERM import protocol Dispatch.DispatchSourceSignal import class Dispatch.DispatchSource +import SwiftParser +import SwiftSyntax #if canImport(BridgeJSCore) import BridgeJSCore @@ -19,6 +20,12 @@ import BridgeJSCore import BridgeJSSkeleton #endif +#if os(Windows) +let PATH_SEPARATOR: Character = ";" +#else +let PATH_SEPARATOR: Character = ":" +#endif + internal func which( _ executable: String, environment: [String: String] = ProcessInfo.processInfo.environment @@ -38,13 +45,8 @@ internal func which( } } } - let pathSeparator: Character - #if os(Windows) - pathSeparator = ";" - #else - pathSeparator = ":" - #endif - let paths = environment["PATH"]?.split(separator: pathSeparator) ?? [] + + let paths = environment["PATH"]?.split(separator: PATH_SEPARATOR) ?? [] for path in paths { let url = URL(fileURLWithPath: String(path)).appendingPathComponent(executable) if checkCandidate(url) { @@ -76,48 +78,61 @@ extension BridgeJSConfig { } } -extension ImportTS { - /// Processes a TypeScript definition file and extracts its API information - public mutating func addSourceFile( - _ sourceFile: String, - tsconfigPath: String, - nodePath: URL - ) throws { - let ts2skeletonPath = URL(fileURLWithPath: #filePath) - .deletingLastPathComponent() - .appendingPathComponent("JavaScript") - .appendingPathComponent("bin") - .appendingPathComponent("ts2skeleton.js") - let arguments = [ts2skeletonPath.path, sourceFile, "--project", tsconfigPath] +/// Invokes ts2swift to convert TypeScript definitions to macro-annotated Swift +/// - Parameters: +/// - dtsFile: Path to the TypeScript definition file +/// - tsconfigPath: Path to the TypeScript project configuration file +/// - nodePath: Path to the node executable +/// - progress: Progress reporting instance +/// - outputPath: Optional path to write the output file. If nil, output is collected from stdout (for testing) +/// - 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, + outputPath: String? = nil +) throws -> String { + let ts2swiftPath = URL(fileURLWithPath: #filePath) + .deletingLastPathComponent() + .appendingPathComponent("JavaScript") + .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]) + } - progress.print("Running ts2skeleton...") - progress.print(" \(([nodePath.path] + arguments).joined(separator: " "))") + progress.print("Running ts2swift...") + progress.print(" \(([nodePath.path] + arguments).joined(separator: " "))") - let process = Process() - let stdoutPipe = Pipe() - nonisolated(unsafe) var stdoutData = Data() + let process = Process() + let stdoutPipe = Pipe() + nonisolated(unsafe) var stdoutData = Data() - process.executableURL = nodePath - process.arguments = arguments - process.standardOutput = stdoutPipe + process.executableURL = nodePath + process.arguments = arguments + process.standardOutput = stdoutPipe - stdoutPipe.fileHandleForReading.readabilityHandler = { handle in - let data = handle.availableData - if data.count > 0 { - stdoutData.append(data) - } - } - try process.forwardTerminationSignals { - try process.run() - process.waitUntilExit() + stdoutPipe.fileHandleForReading.readabilityHandler = { handle in + let data = handle.availableData + if data.count > 0 { + stdoutData.append(data) } + } + try process.forwardTerminationSignals { + try process.run() + process.waitUntilExit() + } - if process.terminationStatus != 0 { - throw BridgeJSCoreError("ts2skeleton returned \(process.terminationStatus)") - } - let skeleton = try JSONDecoder().decode(ImportedFileSkeleton.self, from: stdoutData) - self.addSkeleton(skeleton) + if process.terminationStatus != 0 { + throw BridgeJSCoreError("ts2swift returned \(process.terminationStatus)") } + return String(decoding: stdoutData, as: UTF8.self) } extension Foundation.Process { diff --git a/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSClassMacroTests.swift b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSClassMacroTests.swift new file mode 100644 index 000000000..77dc814eb --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSClassMacroTests.swift @@ -0,0 +1,471 @@ +import SwiftDiagnostics +import SwiftSyntax +import SwiftSyntaxMacroExpansion +import SwiftSyntaxMacrosGenericTestSupport +import Testing +import BridgeJSMacros + +@Suite struct JSClassMacroTests { + private let indentationWidth: Trivia = .spaces(4) + private let macroSpecs: [String: MacroSpec] = [ + "JSClass": MacroSpec(type: JSClassMacro.self, conformances: ["_JSBridgedClass"]) + ] + + @Test func emptyStruct() { + TestSupport.assertMacroExpansion( + """ + @JSClass + struct MyClass { + } + """, + expandedSource: """ + struct MyClass { + + let jsObject: JSObject + + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + } + + extension MyClass: _JSBridgedClass { + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func structWithExistingJSObject() { + TestSupport.assertMacroExpansion( + """ + @JSClass + struct MyClass { + let jsObject: JSObject + } + """, + expandedSource: """ + struct MyClass { + let jsObject: JSObject + + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + } + + extension MyClass: _JSBridgedClass { + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth + ) + } + + @Test func structWithExistingInit() { + TestSupport.assertMacroExpansion( + """ + @JSClass + struct MyClass { + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + } + """, + expandedSource: """ + struct MyClass { + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + + let jsObject: JSObject + } + + extension MyClass: _JSBridgedClass { + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth + ) + } + + @Test func structWithBothExisting() { + TestSupport.assertMacroExpansion( + """ + @JSClass + struct MyClass { + let jsObject: JSObject + + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + } + """, + expandedSource: """ + struct MyClass { + let jsObject: JSObject + + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + } + + extension MyClass: _JSBridgedClass { + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth + ) + } + + @Test func structWithMembers() { + TestSupport.assertMacroExpansion( + """ + @JSClass + struct MyClass { + var name: String + } + """, + expandedSource: """ + struct MyClass { + var name: String + + let jsObject: JSObject + + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + } + + extension MyClass: _JSBridgedClass { + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth + ) + } + + @Test func _class() { + TestSupport.assertMacroExpansion( + """ + @JSClass + class MyClass { + } + """, + expandedSource: """ + class MyClass { + } + """, + diagnostics: [ + DiagnosticSpec( + message: "@JSClass can only be applied to structs.", + line: 1, + column: 1, + notes: [ + NoteSpec( + message: "Use @JSClass on a struct wrapper to synthesize jsObject and JS bridging members.", + line: 1, + column: 1 + ) + ], + fixIts: [ + FixItSpec(message: "Change 'class' to 'struct'") + ] + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth + ) + } + + @Test func _enum() { + TestSupport.assertMacroExpansion( + """ + @JSClass + enum MyEnum { + } + """, + expandedSource: """ + enum MyEnum { + } + """, + diagnostics: [ + DiagnosticSpec( + message: "@JSClass can only be applied to structs.", + line: 1, + column: 1, + notes: [ + NoteSpec( + message: "Use @JSClass on a struct wrapper to synthesize jsObject and JS bridging members.", + line: 1, + column: 1 + ) + ] + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth + ) + } + + @Test func _actor() { + TestSupport.assertMacroExpansion( + """ + @JSClass + actor MyActor { + } + """, + expandedSource: """ + actor MyActor { + } + """, + diagnostics: [ + DiagnosticSpec( + message: "@JSClass can only be applied to structs.", + line: 1, + column: 1, + notes: [ + NoteSpec( + message: "Use @JSClass on a struct wrapper to synthesize jsObject and JS bridging members.", + line: 1, + column: 1 + ) + ] + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth + ) + } + + @Test func structWithDifferentJSObjectName() { + TestSupport.assertMacroExpansion( + """ + @JSClass + struct MyClass { + var otherProperty: String + } + """, + expandedSource: """ + struct MyClass { + var otherProperty: String + + let jsObject: JSObject + + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + } + + extension MyClass: _JSBridgedClass { + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth + ) + } + + @Test func structWithDifferentInit() { + TestSupport.assertMacroExpansion( + """ + @JSClass + struct MyClass { + init(name: String) { + } + } + """, + expandedSource: """ + struct MyClass { + init(name: String) { + } + + let jsObject: JSObject + + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + } + + extension MyClass: _JSBridgedClass { + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth + ) + } + + @Test func structWithMultipleMembers() { + TestSupport.assertMacroExpansion( + """ + @JSClass + struct MyClass { + var name: String + var age: Int + } + """, + expandedSource: """ + struct MyClass { + var name: String + var age: Int + + let jsObject: JSObject + + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + } + + extension MyClass: _JSBridgedClass { + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth + ) + } + + @Test func structWithComment() { + TestSupport.assertMacroExpansion( + """ + /// Documentation comment + @JSClass + struct MyClass { + } + """, + expandedSource: """ + /// Documentation comment + struct MyClass { + + let jsObject: JSObject + + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + } + + extension MyClass: _JSBridgedClass { + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth + ) + } + + @Test func structAlreadyConforms() { + TestSupport.assertMacroExpansion( + """ + @JSClass + struct MyClass: _JSBridgedClass { + } + """, + expandedSource: """ + struct MyClass: _JSBridgedClass { + + let jsObject: JSObject + + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth + ) + } + + @Test func publicStructSynthesizesPublicMembers() { + TestSupport.assertMacroExpansion( + """ + @JSClass + public struct MyClass { + } + """, + expandedSource: """ + public struct MyClass { + + public let jsObject: JSObject + + public init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + } + + extension MyClass: _JSBridgedClass { + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth + ) + } + + @Test func packageStructSynthesizesPackageMembers() { + TestSupport.assertMacroExpansion( + """ + @JSClass + package struct MyClass { + } + """, + expandedSource: """ + package struct MyClass { + + package let jsObject: JSObject + + package init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + } + + extension MyClass: _JSBridgedClass { + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth + ) + } + + @Test func privateStructIsRejected() { + TestSupport.assertMacroExpansion( + """ + @JSClass + private struct MyClass { + } + """, + expandedSource: """ + private struct MyClass { + } + """, + diagnostics: [ + DiagnosticSpec( + message: + "@JSClass does not support private/fileprivate access level. Use internal, package, or public.", + line: 1, + column: 1 + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth + ) + } + + @Test func fileprivateStructIsRejected() { + TestSupport.assertMacroExpansion( + """ + @JSClass + fileprivate struct MyClass { + } + """, + expandedSource: """ + fileprivate struct MyClass { + } + """, + diagnostics: [ + DiagnosticSpec( + message: + "@JSClass does not support private/fileprivate access level. Use internal, package, or public.", + line: 1, + column: 1 + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth + ) + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSFunctionMacroTests.swift b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSFunctionMacroTests.swift new file mode 100644 index 000000000..28eade958 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSFunctionMacroTests.swift @@ -0,0 +1,543 @@ +import SwiftDiagnostics +import SwiftSyntax +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() { + TestSupport.assertMacroExpansion( + """ + @JSFunction + func greet(name: String) throws(JSException) -> String + """, + expandedSource: """ + func greet(name: String) throws(JSException) -> String { + return try _$greet(name) + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func instanceMethodRequiresJSClass() { + TestSupport.assertMacroExpansion( + """ + struct MyClass { + @JSFunction + func getName() throws(JSException) -> String + } + """, + expandedSource: """ + struct MyClass { + func getName() throws(JSException) -> String { + return try _$MyClass_getName(self.jsObject) + } + } + """, + diagnostics: [ + DiagnosticSpec( + message: "JavaScript members must be declared inside a @JSClass struct.", + line: 2, + column: 5 + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func topLevelFunctionVoidReturn() { + TestSupport.assertMacroExpansion( + """ + @JSFunction + func log(message: String) throws(JSException) + """, + expandedSource: """ + func log(message: String) throws(JSException) { + try _$log(message) + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func topLevelFunctionWithExplicitVoidReturn() { + TestSupport.assertMacroExpansion( + """ + @JSFunction + func log(message: String) throws(JSException) -> Void + """, + expandedSource: """ + func log(message: String) throws(JSException) -> Void { + try _$log(message) + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func topLevelFunctionWithEmptyTupleReturn() { + TestSupport.assertMacroExpansion( + """ + @JSFunction + func log(message: String) throws(JSException) -> () + """, + expandedSource: """ + func log(message: String) throws(JSException) -> () { + try _$log(message) + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func topLevelFunctionThrows() { + TestSupport.assertMacroExpansion( + """ + @JSFunction + func parse(json: String) throws(JSException) -> [String: Any] + """, + expandedSource: """ + func parse(json: String) throws(JSException) -> [String: Any] { + return try _$parse(json) + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func topLevelFunctionThrowsMissingType() { + TestSupport.assertMacroExpansion( + """ + @JSFunction + func parse(json: String) throws -> [String: Any] + """, + expandedSource: """ + func parse(json: String) throws -> [String: Any] { + return try _$parse(json) + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func topLevelFunctionThrowsWrongType() { + TestSupport.assertMacroExpansion( + """ + @JSFunction + func parse(json: String) throws(CustomError) -> [String: Any] + """, + expandedSource: """ + func parse(json: String) throws(CustomError) -> [String: Any] { + return try _$parse(json) + } + """, + diagnostics: [ + DiagnosticSpec( + message: "@JSFunction throws must be declared as throws(JSException).", + line: 1, + column: 1, + severity: .error, + notes: [ + NoteSpec( + message: "@JSFunction must propagate JavaScript errors as JSException.", + line: 1, + column: 1 + ) + ], + fixIts: [ + FixItSpec(message: "Declare throws(JSException)") + ] + ) + ], + macroSpecs: macroSpecs, + applyFixIts: ["Declare throws(JSException)"], + fixedSource: """ + @JSFunction + func parse(json: String) throws(JSException) -> [String: Any] + """, + indentationWidth: indentationWidth, + ) + } + + @Test func topLevelFunctionMissingThrowsClause() { + TestSupport.assertMacroExpansion( + """ + @JSFunction + func greet(name: String) -> String + """, + expandedSource: """ + func greet(name: String) -> String { + return try _$greet(name) + } + """, + diagnostics: [ + DiagnosticSpec( + message: "@JSFunction throws must be declared as throws(JSException).", + line: 1, + column: 1, + notes: [ + NoteSpec( + message: "@JSFunction must propagate JavaScript errors as JSException.", + line: 1, + column: 1 + ) + ], + fixIts: [ + FixItSpec(message: "Declare throws(JSException)") + ] + ) + ], + macroSpecs: macroSpecs, + applyFixIts: ["Declare throws(JSException)"], + fixedSource: """ + @JSFunction + func greet(name: String) throws(JSException) -> String + """, + indentationWidth: indentationWidth, + ) + } + + @Test func topLevelFunctionAsync() { + TestSupport.assertMacroExpansion( + """ + @JSFunction + func fetch(url: String) async throws(JSException) -> String + """, + expandedSource: """ + func fetch(url: String) async throws(JSException) -> String { + return try await _$fetch(url) + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func topLevelFunctionAsyncThrows() { + TestSupport.assertMacroExpansion( + """ + @JSFunction + func fetch(url: String) async throws(JSException) -> String + """, + expandedSource: """ + func fetch(url: String) async throws(JSException) -> String { + return try await _$fetch(url) + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func topLevelFunctionWithUnderscoreParameter() { + TestSupport.assertMacroExpansion( + """ + @JSFunction + func process(_ value: Int) throws(JSException) -> Int + """, + expandedSource: """ + func process(_ value: Int) throws(JSException) -> Int { + return try _$process(value) + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func topLevelFunctionWithMultipleParameters() { + TestSupport.assertMacroExpansion( + """ + @JSFunction + func add(a: Int, b: Int) throws(JSException) -> Int + """, + expandedSource: """ + func add(a: Int, b: Int) throws(JSException) -> Int { + return try _$add(a, b) + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func instanceMethod() { + TestSupport.assertMacroExpansion( + """ + @JSClass + struct MyClass { + @JSFunction + func getName() throws(JSException) -> String + } + """, + expandedSource: """ + @JSClass + struct MyClass { + func getName() throws(JSException) -> String { + return try _$MyClass_getName(self.jsObject) + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func staticMethod() { + TestSupport.assertMacroExpansion( + """ + struct MyClass { + @JSFunction + static func create() throws(JSException) -> MyClass + } + """, + expandedSource: """ + struct MyClass { + static func create() throws(JSException) -> MyClass { + return try _$MyClass_create() + } + } + """, + diagnostics: [ + DiagnosticSpec( + message: "JavaScript members must be declared inside a @JSClass struct.", + line: 2, + column: 5 + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func classMethod() { + TestSupport.assertMacroExpansion( + """ + class MyClass { + @JSFunction + class func create() throws(JSException) -> MyClass + } + """, + expandedSource: """ + class MyClass { + class func create() throws(JSException) -> MyClass { + return try _$MyClass_create() + } + } + """, + diagnostics: [ + DiagnosticSpec( + message: "JavaScript members must be declared inside a @JSClass struct.", + line: 2, + column: 5 + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func initializer() { + TestSupport.assertMacroExpansion( + """ + @JSClass + struct MyClass { + @JSFunction + init(name: String) throws(JSException) + } + """, + expandedSource: """ + @JSClass + struct MyClass { + init(name: String) throws(JSException) { + let jsObject = try _$MyClass_init(name) + self.init(unsafelyWrapping: jsObject) + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func initializerThrows() { + TestSupport.assertMacroExpansion( + """ + @JSClass + struct MyClass { + @JSFunction + init(name: String) throws(JSException) + } + """, + expandedSource: """ + @JSClass + struct MyClass { + init(name: String) throws(JSException) { + let jsObject = try _$MyClass_init(name) + self.init(unsafelyWrapping: jsObject) + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func initializerAsyncThrows() { + TestSupport.assertMacroExpansion( + """ + @JSClass + struct MyClass { + @JSFunction + init(name: String) async throws(JSException) + } + """, + expandedSource: """ + @JSClass + struct MyClass { + init(name: String) async throws(JSException) { + let jsObject = try await _$MyClass_init(name) + self.init(unsafelyWrapping: jsObject) + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func initializerWithoutEnclosingType() { + TestSupport.assertMacroExpansion( + """ + @JSFunction + init() + """, + expandedSource: """ + init() { + fatalError("@JSFunction init must be inside a type") + } + """, + diagnostics: [ + DiagnosticSpec( + message: "@JSFunction can only be applied to functions or initializers.", + line: 1, + column: 1, + notes: [ + NoteSpec( + message: "Move this initializer inside a JS wrapper type annotated with @JSClass.", + line: 1, + column: 1 + ) + ] + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func unsupportedDeclaration() { + TestSupport.assertMacroExpansion( + """ + @JSFunction + var property: String + """, + expandedSource: """ + var property: String + """, + diagnostics: [ + DiagnosticSpec( + message: "@JSFunction can only be applied to functions or initializers.", + line: 1, + column: 1, + notes: [ + NoteSpec( + message: + "Place @JSFunction on a function or initializer; use @JSGetter/@JSSetter for properties.", + line: 1, + column: 1 + ) + ] + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func enumInstanceMethod() { + TestSupport.assertMacroExpansion( + """ + @JSClass + enum MyEnum { + @JSFunction + func getValue() throws(JSException) -> Int + } + """, + expandedSource: """ + @JSClass + enum MyEnum { + func getValue() throws(JSException) -> Int { + return try _$MyEnum_getValue(self.jsObject) + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func actorInstanceMethod() { + TestSupport.assertMacroExpansion( + """ + @JSClass + actor MyActor { + @JSFunction + func getValue() throws(JSException) -> Int + } + """, + expandedSource: """ + @JSClass + actor MyActor { + func getValue() throws(JSException) -> Int { + return try _$MyActor_getValue(self.jsObject) + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func functionWithExistingBody() { + TestSupport.assertMacroExpansion( + """ + @JSFunction + func greet(name: String) throws(JSException) -> String { + return "Hello, \\(name)" + } + """, + expandedSource: """ + func greet(name: String) throws(JSException) -> String { + return try _$greet(name) + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSGetterMacroTests.swift b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSGetterMacroTests.swift new file mode 100644 index 000000000..0e4cea844 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSGetterMacroTests.swift @@ -0,0 +1,369 @@ +import SwiftDiagnostics +import SwiftSyntax +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() { + TestSupport.assertMacroExpansion( + """ + @JSGetter + var count: Int + """, + expandedSource: """ + var count: Int { + get throws(JSException) { + return try _$count_get() + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func topLevelLet() { + TestSupport.assertMacroExpansion( + """ + @JSGetter + let constant: String + """, + expandedSource: """ + let constant: String { + get throws(JSException) { + return try _$constant_get() + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func instanceProperty() { + TestSupport.assertMacroExpansion( + """ + @JSClass + struct MyClass { + @JSGetter + var name: String + } + """, + expandedSource: """ + @JSClass + struct MyClass { + var name: String { + get throws(JSException) { + return try _$MyClass_name_get(self.jsObject) + } + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func instancePropertyRequiresJSClass() { + TestSupport.assertMacroExpansion( + """ + struct MyClass { + @JSGetter + var name: String + } + """, + expandedSource: """ + struct MyClass { + var name: String { + get throws(JSException) { + return try _$MyClass_name_get(self.jsObject) + } + } + } + """, + diagnostics: [ + DiagnosticSpec( + message: "JavaScript members must be declared inside a @JSClass struct.", + line: 2, + column: 5 + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func instanceLetProperty() { + TestSupport.assertMacroExpansion( + """ + @JSClass + struct MyClass { + @JSGetter + let id: Int + } + """, + expandedSource: """ + @JSClass + struct MyClass { + let id: Int { + get throws(JSException) { + return try _$MyClass_id_get(self.jsObject) + } + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func staticProperty() { + TestSupport.assertMacroExpansion( + """ + struct MyClass { + @JSGetter + static var version: String + } + """, + expandedSource: """ + struct MyClass { + static var version: String { + get throws(JSException) { + return try _$MyClass_version_get() + } + } + } + """, + diagnostics: [ + DiagnosticSpec( + message: "JavaScript members must be declared inside a @JSClass struct.", + line: 2, + column: 5 + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func classProperty() { + TestSupport.assertMacroExpansion( + """ + class MyClass { + @JSGetter + class var version: String + } + """, + expandedSource: """ + class MyClass { + class var version: String { + get throws(JSException) { + return try _$MyClass_version_get() + } + } + } + """, + diagnostics: [ + DiagnosticSpec( + message: "JavaScript members must be declared inside a @JSClass struct.", + line: 2, + column: 5 + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func enumProperty() { + TestSupport.assertMacroExpansion( + """ + @JSClass + enum MyEnum { + @JSGetter + var value: Int + } + """, + expandedSource: """ + @JSClass + enum MyEnum { + var value: Int { + get throws(JSException) { + return try _$MyEnum_value_get(self.jsObject) + } + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func actorProperty() { + TestSupport.assertMacroExpansion( + """ + @JSClass + actor MyActor { + @JSGetter + var state: String + } + """, + expandedSource: """ + @JSClass + actor MyActor { + var state: String { + get throws(JSException) { + return try _$MyActor_state_get(self.jsObject) + } + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func variableWithExistingAccessor() { + TestSupport.assertMacroExpansion( + """ + @JSGetter + var count: Int { + return 0 + } + """, + expandedSource: """ + var count: Int { + get { + return 0 + } + get throws(JSException) { + return try _$count_get() + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func variableWithInitializer() { + TestSupport.assertMacroExpansion( + """ + @JSGetter + var count: Int = 0 + """, + expandedSource: """ + var count: Int { + get throws(JSException) { + return try _$count_get() + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func multipleBindings() { + TestSupport.assertMacroExpansion( + """ + @JSGetter + var x: Int, y: Int + """, + expandedSource: """ + var x: Int, y: Int + """, + diagnostics: [ + DiagnosticSpec( + 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 + ), + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func unsupportedDeclaration() { + TestSupport.assertMacroExpansion( + """ + @JSGetter + func test() {} + """, + expandedSource: """ + func test() {} + """, + diagnostics: [ + DiagnosticSpec( + message: "@JSGetter can only be applied to single-variable declarations.", + line: 1, + column: 1, + severity: .error, + notes: [ + NoteSpec( + message: "@JSGetter must be attached to a single stored or computed property.", + line: 1, + column: 1 + ) + ] + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + #if canImport(SwiftSyntax602) + // https://github.com/swiftlang/swift-syntax/pull/2722 + @Test func variableWithTrailingComment() { + TestSupport.assertMacroExpansion( + """ + @JSGetter + var count: Int // comment + """, + expandedSource: """ + var count: Int { // comment + get throws(JSException) { + return try _$count_get() + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + #endif + + @Test func variableWithUnderscoreName() { + TestSupport.assertMacroExpansion( + """ + @JSGetter + var _internal: String + """, + expandedSource: """ + var _internal: String { + get throws(JSException) { + return try _$_internal_get() + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSSetterMacroTests.swift b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSSetterMacroTests.swift new file mode 100644 index 000000000..00d959921 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSSetterMacroTests.swift @@ -0,0 +1,468 @@ +import SwiftDiagnostics +import SwiftSyntax +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() { + TestSupport.assertMacroExpansion( + """ + @JSSetter + func setFoo(_ value: Foo) throws(JSException) + """, + expandedSource: """ + func setFoo(_ value: Foo) throws(JSException) { + try _$foo_set(value) + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func topLevelSetterWithNamedParameter() { + TestSupport.assertMacroExpansion( + """ + @JSSetter + func setCount(count: Int) throws(JSException) + """, + expandedSource: """ + func setCount(count: Int) throws(JSException) { + try _$count_set(count) + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func instanceSetter() { + TestSupport.assertMacroExpansion( + """ + @JSClass + struct MyClass { + @JSSetter + func setName(_ name: String) throws(JSException) + } + """, + expandedSource: """ + @JSClass + struct MyClass { + func setName(_ name: String) throws(JSException) { + try _$MyClass_name_set(self.jsObject, name) + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func instanceSetterRequiresJSClass() { + TestSupport.assertMacroExpansion( + """ + struct MyClass { + @JSSetter + func setName(_ name: String) throws(JSException) + } + """, + expandedSource: """ + struct MyClass { + func setName(_ name: String) throws(JSException) { + try _$MyClass_name_set(self.jsObject, name) + } + } + """, + diagnostics: [ + DiagnosticSpec( + message: "JavaScript members must be declared inside a @JSClass struct.", + line: 2, + column: 5 + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func staticSetter() { + TestSupport.assertMacroExpansion( + """ + struct MyClass { + @JSSetter + static func setVersion(_ version: String) throws(JSException) + } + """, + expandedSource: """ + struct MyClass { + static func setVersion(_ version: String) throws(JSException) { + try _$MyClass_version_set(version) + } + } + """, + diagnostics: [ + DiagnosticSpec( + message: "JavaScript members must be declared inside a @JSClass struct.", + line: 2, + column: 5 + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func classSetter() { + TestSupport.assertMacroExpansion( + """ + class MyClass { + @JSSetter + class func setConfig(_ config: Config) throws(JSException) + } + """, + expandedSource: """ + class MyClass { + class func setConfig(_ config: Config) throws(JSException) { + try _$MyClass_config_set(config) + } + } + """, + diagnostics: [ + DiagnosticSpec( + message: "JavaScript members must be declared inside a @JSClass struct.", + line: 2, + column: 5 + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func enumSetter() { + TestSupport.assertMacroExpansion( + """ + @JSClass + enum MyEnum { + @JSSetter + func setValue(_ value: Int) throws(JSException) + } + """, + expandedSource: """ + @JSClass + enum MyEnum { + func setValue(_ value: Int) throws(JSException) { + try _$MyEnum_value_set(self.jsObject, value) + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func actorSetter() { + TestSupport.assertMacroExpansion( + """ + @JSClass + actor MyActor { + @JSSetter + func setState(_ state: String) throws(JSException) + } + """, + expandedSource: """ + @JSClass + actor MyActor { + func setState(_ state: String) throws(JSException) { + try _$MyActor_state_set(self.jsObject, state) + } + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func setterWithExistingBody() { + TestSupport.assertMacroExpansion( + """ + @JSSetter + func setFoo(_ value: Foo) throws(JSException) { + print("Setting foo") + } + """, + expandedSource: """ + func setFoo(_ value: Foo) throws(JSException) { + try _$foo_set(value) + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func invalidSetterName() { + TestSupport.assertMacroExpansion( + """ + @JSSetter + func updateFoo(_ value: Foo) throws(JSException) + """, + expandedSource: """ + func updateFoo(_ value: Foo) throws(JSException) { + fatalError("@JSSetter function name must start with 'set' followed by a property name") + } + """, + diagnostics: [ + DiagnosticSpec( + message: + "@JSSetter function name must start with 'set' followed by a property name (e.g., 'setFoo').", + line: 1, + column: 1, + notes: [ + NoteSpec( + message: "Setter names must start with 'set' followed by the property name.", + line: 2, + column: 6 + ) + ], + fixIts: [ + FixItSpec(message: "Rename setter to 'setFoo'") + ] + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func setterNameTooShort() { + TestSupport.assertMacroExpansion( + """ + @JSSetter + func set(_ value: Foo) throws(JSException) + """, + expandedSource: """ + func set(_ value: Foo) throws(JSException) { + fatalError("@JSSetter function name must start with 'set' followed by a property name") + } + """, + diagnostics: [ + DiagnosticSpec( + message: + "@JSSetter function name must start with 'set' followed by a property name (e.g., 'setFoo').", + line: 1, + column: 1, + notes: [ + NoteSpec( + message: "Setter names must start with 'set' followed by the property name.", + line: 2, + column: 6 + ) + ], + fixIts: [ + FixItSpec(message: "Rename setter to 'setFoo'") + ] + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func setterWithoutParameter() { + TestSupport.assertMacroExpansion( + """ + @JSSetter + func setFoo() throws(JSException) + """, + expandedSource: """ + func setFoo() throws(JSException) { + fatalError("@JSSetter function must have at least one parameter") + } + """, + diagnostics: [ + DiagnosticSpec( + message: "@JSSetter function must have at least one parameter.", + line: 1, + column: 1, + notes: [ + NoteSpec( + message: "@JSSetter needs a parameter for the value being assigned.", + line: 1, + column: 1 + ) + ], + fixIts: [ + FixItSpec(message: "Add a value parameter to the setter") + ] + ) + ], + macroSpecs: macroSpecs, + applyFixIts: ["Add a value parameter to the setter"], + fixedSource: """ + @JSSetter + func setFoo(_ value: <#Type#>) throws(JSException) + """, + indentationWidth: indentationWidth, + ) + } + + @Test func setterMissingThrows() { + TestSupport.assertMacroExpansion( + """ + @JSSetter + func setFoo(_ value: Foo) + """, + expandedSource: """ + func setFoo(_ value: Foo) { + try _$foo_set(value) + } + """, + diagnostics: [ + DiagnosticSpec( + message: "@JSSetter function must declare throws(JSException).", + line: 1, + column: 1, + notes: [ + NoteSpec( + message: "@JSSetter must propagate JavaScript errors as JSException.", + line: 1, + column: 1 + ) + ], + fixIts: [ + FixItSpec(message: "Declare throws(JSException)") + ] + ) + ], + macroSpecs: macroSpecs, + applyFixIts: ["Declare throws(JSException)"], + fixedSource: """ + @JSSetter + func setFoo(_ value: Foo) throws(JSException) + """, + indentationWidth: indentationWidth, + ) + } + + @Test func setterThrowsWrongType() { + TestSupport.assertMacroExpansion( + """ + @JSSetter + func setFoo(_ value: Foo) throws(CustomError) + """, + expandedSource: """ + func setFoo(_ value: Foo) throws(CustomError) { + try _$foo_set(value) + } + """, + diagnostics: [ + DiagnosticSpec( + message: "@JSSetter function must declare throws(JSException).", + line: 1, + column: 1, + notes: [ + NoteSpec( + message: "@JSSetter must propagate JavaScript errors as JSException.", + line: 1, + column: 1 + ) + ], + fixIts: [ + FixItSpec(message: "Declare throws(JSException)") + ] + ) + ], + macroSpecs: macroSpecs, + applyFixIts: ["Declare throws(JSException)"], + fixedSource: """ + @JSSetter + func setFoo(_ value: Foo) throws(JSException) + """, + indentationWidth: indentationWidth, + ) + } + + @Test func setterThrowsErrorAccepted() { + TestSupport.assertMacroExpansion( + """ + @JSSetter + func setFoo(_ value: Foo) throws(Error) + """, + expandedSource: """ + func setFoo(_ value: Foo) throws(Error) { + try _$foo_set(value) + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func unsupportedDeclaration() { + TestSupport.assertMacroExpansion( + """ + @JSSetter + var property: String + """, + expandedSource: """ + var property: String + """, + diagnostics: [ + DiagnosticSpec( + message: "@JSSetter can only be applied to functions.", + line: 1, + column: 1, + notes: [ + NoteSpec( + message: "@JSSetter should be attached to a method that writes a JavaScript property.", + line: 1, + column: 1 + ) + ] + ) + ], + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func setterWithMultipleWords() { + TestSupport.assertMacroExpansion( + """ + @JSSetter + func setConnectionTimeout(_ timeout: Int) throws(JSException) + """, + expandedSource: """ + func setConnectionTimeout(_ timeout: Int) throws(JSException) { + try _$connectionTimeout_set(timeout) + } + """, + macroSpecs: macroSpecs, + indentationWidth: indentationWidth, + ) + } + + @Test func setterWithSingleLetterProperty() { + TestSupport.assertMacroExpansion( + """ + @JSSetter + func setX(_ x: Int) throws(JSException) + """, + expandedSource: """ + func setX(_ x: Int) throws(JSException) { + try _$x_set(x) + } + """, + 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/BridgeJSCodegenTests.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/BridgeJSCodegenTests.swift new file mode 100644 index 000000000..9754fbced --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/BridgeJSCodegenTests.swift @@ -0,0 +1,187 @@ +import Foundation +import SwiftSyntax +import SwiftParser +import Testing + +@testable import BridgeJSCore +@testable import BridgeJSSkeleton + +@Suite struct BridgeJSCodegenTests { + static let inputsDirectory = URL(fileURLWithPath: #filePath).deletingLastPathComponent().appendingPathComponent( + "Inputs" + ).appendingPathComponent("MacroSwift") + static let multifileInputsDirectory = URL(fileURLWithPath: #filePath).deletingLastPathComponent() + .appendingPathComponent("Inputs").appendingPathComponent("MacroSwift").appendingPathComponent("Multifile") + + private func snapshotCodegen( + skeleton: BridgeJSSkeleton, + name: String, + filePath: String = #filePath, + function: String = #function, + sourceLocation: Testing.SourceLocation = #_sourceLocation + ) throws { + var swiftParts: [String] = [] + if let closureSupport = try ClosureCodegen().renderSupport(for: skeleton) { + swiftParts.append(closureSupport) + } + if let exported = skeleton.exported { + let exportSwift = ExportSwift( + progress: .silent, + moduleName: skeleton.moduleName, + skeleton: exported + ) + if let s = try exportSwift.finalize() { + swiftParts.append(s) + } + } + if let imported = skeleton.imported { + let importTS = ImportTS(progress: .silent, moduleName: skeleton.moduleName, skeleton: imported) + if let s = try importTS.finalize() { + swiftParts.append(s) + } + } + let combinedSwift = + swiftParts + .map { $0.trimmingCharacters(in: .newlines) } + .filter { !$0.isEmpty } + .joined(separator: "\n\n") + try assertSnapshot( + name: name, + filePath: filePath, + function: function, + sourceLocation: sourceLocation, + input: combinedSwift.data(using: String.Encoding.utf8)!, + fileExtension: "swift" + ) + let encoder = JSONEncoder() + encoder.outputFormatting = [.prettyPrinted, .sortedKeys] + let skeletonData = try encoder.encode(skeleton) + try assertSnapshot( + name: name, + filePath: filePath, + function: function, + sourceLocation: sourceLocation, + input: skeletonData, + fileExtension: "json" + ) + } + + static func collectInputs() -> [String] { + let fileManager = FileManager.default + let inputs = try! fileManager.contentsOfDirectory(atPath: Self.inputsDirectory.path) + return inputs.filter { $0.hasSuffix(".swift") }.sorted() + } + + @Test(arguments: collectInputs()) + func codegenSnapshot(input: String) throws { + let url = Self.inputsDirectory.appendingPathComponent(input) + let name = url.deletingPathExtension().lastPathComponent + let sourceFile = Parser.parse(source: try String(contentsOf: url, encoding: .utf8)) + let swiftAPI = SwiftToSkeleton(progress: .silent, moduleName: "TestModule", exposeToGlobal: false) + swiftAPI.addSourceFile(sourceFile, inputFilePath: input) + let skeleton = try swiftAPI.finalize() + try snapshotCodegen(skeleton: skeleton, name: name) + } + + @Test(arguments: [ + "Namespaces.swift", + "StaticFunctions.swift", + "StaticProperties.swift", + "EnumNamespace.swift", + ]) + func codegenSnapshotWithGlobal(input: String) throws { + let url = Self.inputsDirectory.appendingPathComponent(input) + let name = url.deletingPathExtension().lastPathComponent + let sourceFile = Parser.parse(source: try String(contentsOf: url, encoding: .utf8)) + let swiftAPI = SwiftToSkeleton(progress: .silent, moduleName: "TestModule", exposeToGlobal: true) + swiftAPI.addSourceFile(sourceFile, inputFilePath: input) + let skeleton = try swiftAPI.finalize() + try snapshotCodegen(skeleton: skeleton, name: name + ".Global") + } + + @Test + func codegenCrossFileTypeResolution() throws { + let swiftAPI = SwiftToSkeleton(progress: .silent, moduleName: "TestModule", exposeToGlobal: false) + let classBURL = Self.multifileInputsDirectory.appendingPathComponent("CrossFileClassB.swift") + swiftAPI.addSourceFile( + Parser.parse(source: try String(contentsOf: classBURL, encoding: .utf8)), + inputFilePath: "CrossFileClassB.swift" + ) + let classAURL = Self.multifileInputsDirectory.appendingPathComponent("CrossFileClassA.swift") + swiftAPI.addSourceFile( + Parser.parse(source: try String(contentsOf: classAURL, encoding: .utf8)), + inputFilePath: "CrossFileClassA.swift" + ) + let skeleton = try swiftAPI.finalize() + try snapshotCodegen(skeleton: skeleton, name: "CrossFileTypeResolution") + } + + @Test + func codegenCrossFileTypeResolutionReverseOrder() throws { + let swiftAPI = SwiftToSkeleton(progress: .silent, moduleName: "TestModule", exposeToGlobal: false) + let classAURL = Self.multifileInputsDirectory.appendingPathComponent("CrossFileClassA.swift") + swiftAPI.addSourceFile( + Parser.parse(source: try String(contentsOf: classAURL, encoding: .utf8)), + inputFilePath: "CrossFileClassA.swift" + ) + let classBURL = Self.multifileInputsDirectory.appendingPathComponent("CrossFileClassB.swift") + swiftAPI.addSourceFile( + Parser.parse(source: try String(contentsOf: classBURL, encoding: .utf8)), + inputFilePath: "CrossFileClassB.swift" + ) + let skeleton = try swiftAPI.finalize() + try snapshotCodegen(skeleton: skeleton, name: "CrossFileTypeResolution.ReverseOrder") + } + + @Test + func codegenCrossFileFunctionTypes() throws { + let swiftAPI = SwiftToSkeleton(progress: .silent, moduleName: "TestModule", exposeToGlobal: false) + let functionBURL = Self.multifileInputsDirectory.appendingPathComponent("CrossFileFunctionB.swift") + swiftAPI.addSourceFile( + Parser.parse(source: try String(contentsOf: functionBURL, encoding: .utf8)), + inputFilePath: "CrossFileFunctionB.swift" + ) + let functionAURL = Self.multifileInputsDirectory.appendingPathComponent("CrossFileFunctionA.swift") + swiftAPI.addSourceFile( + Parser.parse(source: try String(contentsOf: functionAURL, encoding: .utf8)), + inputFilePath: "CrossFileFunctionA.swift" + ) + let skeleton = try swiftAPI.finalize() + try snapshotCodegen(skeleton: skeleton, name: "CrossFileFunctionTypes") + } + + @Test + func codegenCrossFileFunctionTypesReverseOrder() throws { + let swiftAPI = SwiftToSkeleton(progress: .silent, moduleName: "TestModule", exposeToGlobal: false) + let functionAURL = Self.multifileInputsDirectory.appendingPathComponent("CrossFileFunctionA.swift") + swiftAPI.addSourceFile( + Parser.parse(source: try String(contentsOf: functionAURL, encoding: .utf8)), + inputFilePath: "CrossFileFunctionA.swift" + ) + let functionBURL = Self.multifileInputsDirectory.appendingPathComponent("CrossFileFunctionB.swift") + swiftAPI.addSourceFile( + Parser.parse(source: try String(contentsOf: functionBURL, encoding: .utf8)), + inputFilePath: "CrossFileFunctionB.swift" + ) + let skeleton = try swiftAPI.finalize() + try snapshotCodegen(skeleton: skeleton, name: "CrossFileFunctionTypes.ReverseOrder") + } + + @Test + func codegenSkipsEmptySkeletons() throws { + let swiftAPI = SwiftToSkeleton(progress: .silent, moduleName: "TestModule", exposeToGlobal: false) + let importedURL = Self.multifileInputsDirectory.appendingPathComponent("ImportedFunctions.swift") + swiftAPI.addSourceFile( + Parser.parse(source: try String(contentsOf: importedURL, encoding: .utf8)), + inputFilePath: "ImportedFunctions.swift" + ) + let exportedOnlyURL = Self.multifileInputsDirectory.appendingPathComponent("ExportedOnly.swift") + swiftAPI.addSourceFile( + Parser.parse(source: try String(contentsOf: exportedOnlyURL, encoding: .utf8)), + inputFilePath: "ExportedOnly.swift" + ) + let skeleton = try swiftAPI.finalize() + #expect(skeleton.exported == nil, "Empty exported skeleton should be omitted") + try snapshotCodegen(skeleton: skeleton, name: "CrossFileSkipsEmptySkeletons") + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/BridgeJSLinkTests.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/BridgeJSLinkTests.swift index 37edf8308..711b04512 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/BridgeJSLinkTests.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/BridgeJSLinkTests.swift @@ -4,7 +4,7 @@ import SwiftParser import Testing @testable import BridgeJSLink @testable import BridgeJSCore -@testable import TS2Skeleton +@testable import BridgeJSSkeleton @Suite struct BridgeJSLinkTests { private func snapshot( @@ -35,7 +35,7 @@ import Testing static let inputsDirectory = URL(fileURLWithPath: #filePath).deletingLastPathComponent().appendingPathComponent( "Inputs" - ) + ).appendingPathComponent("MacroSwift") static func collectInputs(extension: String) -> [String] { let fileManager = FileManager.default @@ -44,38 +44,65 @@ import Testing } @Test(arguments: collectInputs(extension: ".swift")) - func snapshotExport(input: String) throws { + func snapshot(input: String) throws { let url = Self.inputsDirectory.appendingPathComponent(input) - let sourceFile = Parser.parse(source: try String(contentsOf: url, encoding: .utf8)) - let swiftAPI = ExportSwift(progress: .silent, moduleName: "TestModule") - try swiftAPI.addSourceFile(sourceFile, input) let name = url.deletingPathExtension().lastPathComponent - let (_, outputSkeleton) = try #require(try swiftAPI.finalize()) + let sourceFile = Parser.parse(source: try String(contentsOf: url, encoding: .utf8)) + let importSwift = SwiftToSkeleton(progress: .silent, moduleName: "TestModule", exposeToGlobal: false) + importSwift.addSourceFile(sourceFile, inputFilePath: "\(name).swift") + let importResult = try importSwift.finalize() + var bridgeJSLink = BridgeJSLink(sharedMemory: false) let encoder = JSONEncoder() encoder.outputFormatting = [.prettyPrinted, .sortedKeys] - let outputSkeletonData = try encoder.encode(outputSkeleton) - var bridgeJSLink = BridgeJSLink(sharedMemory: false) - try bridgeJSLink.addExportedSkeletonFile(data: outputSkeletonData) - try snapshot(bridgeJSLink: bridgeJSLink, name: name + ".Export") + let unifiedData = try encoder.encode(importResult) + try bridgeJSLink.addSkeletonFile(data: unifiedData) + try snapshot(bridgeJSLink: bridgeJSLink, name: name) } - @Test(arguments: collectInputs(extension: ".d.ts")) - func snapshotImport(input: String) throws { - let url = Self.inputsDirectory.appendingPathComponent(input) - let tsconfigPath = url.deletingLastPathComponent().appendingPathComponent("tsconfig.json") + @Test(arguments: [ + "Namespaces.swift", + "StaticFunctions.swift", + "StaticProperties.swift", + "EnumNamespace.swift", + ]) + func snapshotExportWithGlobal(inputFile: String) throws { + let url = Self.inputsDirectory.appendingPathComponent(inputFile) + let sourceFile = Parser.parse(source: try String(contentsOf: url, encoding: .utf8)) + let swiftAPI = SwiftToSkeleton(progress: .silent, moduleName: "TestModule", exposeToGlobal: true) + swiftAPI.addSourceFile(sourceFile, inputFilePath: inputFile) + let name = url.deletingPathExtension().lastPathComponent + let outputSkeleton = try swiftAPI.finalize() + let bridgeJSLink: BridgeJSLink = BridgeJSLink( + skeletons: [ + outputSkeleton + ], + sharedMemory: false + ) + try snapshot(bridgeJSLink: bridgeJSLink, name: name + ".Global") + } - var importTS = ImportTS(progress: .silent, moduleName: "TestModule") - let nodePath = try #require(which("node")) - try importTS.addSourceFile(url.path, tsconfigPath: tsconfigPath.path, nodePath: nodePath) - let name = url.deletingPathExtension().deletingPathExtension().lastPathComponent + @Test + func snapshotMixedModuleExposure() throws { + let globalURL = Self.inputsDirectory.appendingPathComponent("MixedGlobal.swift") + let globalSourceFile = Parser.parse(source: try String(contentsOf: globalURL, encoding: .utf8)) + let globalAPI = SwiftToSkeleton(progress: .silent, moduleName: "GlobalModule", exposeToGlobal: true) + globalAPI.addSourceFile(globalSourceFile, inputFilePath: "MixedGlobal.swift") + let globalSkeleton = try globalAPI.finalize() - let encoder = JSONEncoder() - encoder.outputFormatting = [.prettyPrinted, .sortedKeys] - let outputSkeletonData = try encoder.encode(importTS.skeleton) + let privateURL = Self.inputsDirectory.appendingPathComponent("MixedPrivate.swift") + let privateSourceFile = Parser.parse(source: try String(contentsOf: privateURL, encoding: .utf8)) + let privateAPI = SwiftToSkeleton(progress: .silent, moduleName: "PrivateModule", exposeToGlobal: false) + privateAPI.addSourceFile(privateSourceFile, inputFilePath: "MixedPrivate.swift") + let privateSkeleton = try privateAPI.finalize() - var bridgeJSLink = BridgeJSLink(sharedMemory: false) - try bridgeJSLink.addImportedSkeletonFile(data: outputSkeletonData) - try snapshot(bridgeJSLink: bridgeJSLink, name: name + ".Import") + let bridgeJSLink = BridgeJSLink( + skeletons: [ + globalSkeleton, + privateSkeleton, + ], + sharedMemory: false + ) + try snapshot(bridgeJSLink: bridgeJSLink, name: "MixedModules") } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift new file mode 100644 index 000000000..500a5db95 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift @@ -0,0 +1,182 @@ +import SwiftParser +import SwiftSyntax +import Testing + +@testable import BridgeJSCore + +@Suite struct DiagnosticsTests { + /// Returns the first parameter's type node from a function in the source (the first `@JS func`-like decl), for pinpointing diagnostics. + private func firstParameterTypeNode(source: String) -> TypeSyntax? { + let tree = Parser.parse(source: source) + for stmt in tree.statements { + if let funcDecl = stmt.item.as(FunctionDeclSyntax.self), + let firstParam = funcDecl.signature.parameterClause.parameters.first + { + return firstParam.type + } + } + return nil + } + + @Test + func diagnosticIncludesLocationSourceAndHint() throws { + let source = "@JS func foo(_ bar: A) {}\n" + let typeNode = try #require(firstParameterTypeNode(source: source)) + let diagnostic = DiagnosticError( + node: typeNode, + message: "Unsupported type 'A'.", + hint: "Only primitive types and types defined in the same module are allowed" + ) + let description = diagnostic.formattedDescription(fileName: "-", colorize: false) + let expectedPrefix = """ + :1:21: error: Unsupported type 'A'. + 1 | @JS func foo(_ bar: A) {} + | `- error: Unsupported type 'A'. + 2 | + """.trimmingCharacters(in: .whitespacesAndNewlines) + #expect(description.hasPrefix(expectedPrefix)) + #expect(description.contains("Hint: Only primitive types and types defined in the same module are allowed")) + } + + @Test + func diagnosticOmitsHintWhenNotProvided() throws { + let source = "@JS static func foo() {}\n" + let tree = Parser.parse(source: source) + let diagnostic = DiagnosticError( + node: tree, + message: "Top-level functions cannot be static", + hint: nil + ) + let description = diagnostic.formattedDescription(fileName: "-", colorize: false) + let expectedPrefix = """ + :1:1: error: Top-level functions cannot be static + 1 | @JS static func foo() {} + | `- error: Top-level functions cannot be static + 2 | + """.trimmingCharacters(in: .whitespacesAndNewlines) + #expect(description.hasPrefix(expectedPrefix)) + #expect(!description.contains("Hint:")) + } + + @Test + func diagnosticUsesGivenFileNameNotStdin() throws { + let source = "@JS func foo(_ bar: A) {}\n" + let typeNode = try #require(firstParameterTypeNode(source: source)) + let diagnostic = DiagnosticError( + node: typeNode, + message: "Unsupported type 'A'.", + hint: nil + ) + let description = diagnostic.formattedDescription(fileName: "Sources/Foo.swift", colorize: false) + #expect(description.hasPrefix("Sources/Foo.swift:1:21: error: Unsupported type 'A'.")) + } + + @Test + func diagnosticWithColorizeTrueIncludesANSISequences() throws { + let source = "@JS func foo(_ bar: A) {}\n" + let typeNode = try #require(firstParameterTypeNode(source: source)) + let diagnostic = DiagnosticError( + node: typeNode, + message: "Unsupported type 'A'.", + hint: nil + ) + let description = diagnostic.formattedDescription(fileName: "-", colorize: true) + let esc = "\u{001B}" + let boldRed = "\(esc)[1;31m" + let boldDefault = "\(esc)[1;39m" + let reset = "\(esc)[0;0m" + let cyan = "\(esc)[0;36m" + let underline = "\(esc)[4;39m" + let expected = + ":1:21: \(boldRed)error: \(boldDefault)Unsupported type 'A'.\(reset)\n" + + "\(cyan) 1\(reset) | @JS func foo(_ bar: \(underline)A\(reset)) {}\n" + + " | `- \(boldRed)error: \(boldDefault)Unsupported type 'A'.\(reset)\n" + + "\(cyan) 2\(reset) | " + #expect(description == expected) + } + + // MARK: - Context source lines + + @Test + func showsOnePreviousLineWhenErrorNotOnFirstLine() throws { + let source = """ + preamble + @JS func foo(_ bar: A) {} + """ + let typeNode = try #require(firstParameterTypeNode(source: source)) + let diagnostic = DiagnosticError(node: typeNode, message: "Unsupported type 'A'.", hint: nil) + let description = diagnostic.formattedDescription(fileName: "-", colorize: false) + #expect(description.contains(" 1 | preamble")) + #expect(description.contains(" 2 | @JS func foo(_ bar: A) {}")) + #expect(description.contains(":2:")) + } + + @Test + func showsThreePreviousLinesWhenAvailable() throws { + let source = """ + first + second + third + @JS func foo(_ bar: A) {} + """ + let typeNode = try #require(firstParameterTypeNode(source: source)) + let diagnostic = DiagnosticError(node: typeNode, message: "Unsupported type 'A'.", hint: nil) + let description = diagnostic.formattedDescription(fileName: "-", colorize: false) + #expect(description.contains(" 1 | first")) + #expect(description.contains(" 2 | second")) + #expect(description.contains(" 3 | third")) + #expect(description.contains(" 4 | @JS func foo(_ bar: A) {}")) + #expect(description.contains(":4:")) + } + + @Test + func capsContextAtThreePreviousLines() throws { + let source = """ + line0 + line1 + line2 + line3 + @JS func foo(_ bar: A) {} + """ + let typeNode = try #require(firstParameterTypeNode(source: source)) + let diagnostic = DiagnosticError(node: typeNode, message: "Unsupported type 'A'.", hint: nil) + let description = diagnostic.formattedDescription(fileName: "-", colorize: false) + #expect(!description.contains(" 1 | line0")) + #expect(description.contains(" 2 | line1")) + #expect(description.contains(" 3 | line2")) + #expect(description.contains(" 4 | line3")) + #expect(description.contains(" 5 | @JS func foo(_ bar: A) {}")) + #expect(description.contains(":5:")) + } + + @Test + func includesNextLineAfterErrorLine() throws { + let source = """ + @JS func foo( + _ bar: A + ) {} + """ + let typeNode = try #require(firstParameterTypeNode(source: source)) + let diagnostic = DiagnosticError(node: typeNode, message: "Unsupported type 'A'.", hint: nil) + let description = diagnostic.formattedDescription(fileName: "-", colorize: false) + #expect(description.contains(" 1 | @JS func foo(")) + #expect(description.contains(" 2 | _ bar: A")) + #expect(description.contains(" 3 | ) {}")) + #expect(description.contains(":2:")) + } + + @Test + func omitsNextLineWhenErrorIsOnLastLine() throws { + let source = """ + preamble + @JS func foo(_ bar: A) + """ + let typeNode = try #require(firstParameterTypeNode(source: source)) + let diagnostic = DiagnosticError(node: typeNode, message: "Unsupported type 'A'.", hint: nil) + let description = diagnostic.formattedDescription(fileName: "-", colorize: false) + #expect(description.contains(" 2 | @JS func foo(_ bar: A)")) + #expect(description.contains(":2:")) + // No line 3 in source, so output must not show a " 3 |" context line after the pointer + #expect(!description.contains(" 3 |")) + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/ExportSwiftTests.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/ExportSwiftTests.swift deleted file mode 100644 index e184116fe..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/ExportSwiftTests.swift +++ /dev/null @@ -1,57 +0,0 @@ -import Foundation -import SwiftSyntax -import SwiftParser -import Testing - -@testable import BridgeJSCore - -@Suite struct ExportSwiftTests { - private func snapshot( - swiftAPI: ExportSwift, - name: String? = nil, - filePath: String = #filePath, - function: String = #function, - sourceLocation: Testing.SourceLocation = #_sourceLocation - ) throws { - let (outputSwift, outputSkeleton) = try #require(try swiftAPI.finalize()) - try assertSnapshot( - name: name, - filePath: filePath, - function: function, - sourceLocation: sourceLocation, - input: outputSwift.data(using: .utf8)!, - fileExtension: "swift" - ) - let encoder = JSONEncoder() - encoder.outputFormatting = [.prettyPrinted, .sortedKeys] - let outputSkeletonData = try encoder.encode(outputSkeleton) - try assertSnapshot( - name: name, - filePath: filePath, - function: function, - sourceLocation: sourceLocation, - input: outputSkeletonData, - fileExtension: "json" - ) - } - - static let inputsDirectory = URL(fileURLWithPath: #filePath).deletingLastPathComponent().appendingPathComponent( - "Inputs" - ) - - static func collectInputs() -> [String] { - let fileManager = FileManager.default - let inputs = try! fileManager.contentsOfDirectory(atPath: Self.inputsDirectory.path) - return inputs.filter { $0.hasSuffix(".swift") } - } - - @Test(arguments: collectInputs()) - func snapshot(input: String) throws { - let swiftAPI = ExportSwift(progress: .silent, moduleName: "TestModule") - let url = Self.inputsDirectory.appendingPathComponent(input) - let sourceFile = Parser.parse(source: try String(contentsOf: url, encoding: .utf8)) - try swiftAPI.addSourceFile(sourceFile, input) - let name = url.deletingPathExtension().lastPathComponent - try snapshot(swiftAPI: swiftAPI, name: name) - } -} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/ImportTSTests.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/ImportTSTests.swift deleted file mode 100644 index ef642ed3a..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/ImportTSTests.swift +++ /dev/null @@ -1,34 +0,0 @@ -import Testing -import Foundation -@testable import BridgeJSCore -@testable import TS2Skeleton - -@Suite struct ImportTSTests { - static let inputsDirectory = URL(fileURLWithPath: #filePath).deletingLastPathComponent().appendingPathComponent( - "Inputs" - ) - - static func collectInputs() -> [String] { - let fileManager = FileManager.default - let inputs = try! fileManager.contentsOfDirectory(atPath: Self.inputsDirectory.path) - return inputs.filter { $0.hasSuffix(".d.ts") } - } - - @Test(arguments: collectInputs()) - func snapshot(input: String) throws { - var api = ImportTS(progress: .silent, moduleName: "Check") - let url = Self.inputsDirectory.appendingPathComponent(input) - let nodePath = try #require(which("node")) - let tsconfigPath = url.deletingLastPathComponent().appendingPathComponent("tsconfig.json") - try api.addSourceFile(url.path, tsconfigPath: tsconfigPath.path, nodePath: nodePath) - let outputSwift = try #require(try api.finalize()) - let name = url.deletingPathExtension().deletingPathExtension().deletingPathExtension().lastPathComponent - try assertSnapshot( - name: name, - filePath: #filePath, - function: #function, - input: outputSwift.data(using: .utf8)!, - fileExtension: "swift" - ) - } -} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/ArrayParameter.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/ArrayParameter.d.ts deleted file mode 100644 index 59674e071..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/ArrayParameter.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function checkArray(a: number[]): void; -export function checkArrayWithLength(a: number[], b: number): void; -export function checkArray(a: Array): void; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/ArrayTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/ArrayTypes.swift new file mode 100644 index 000000000..0cea90512 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/ArrayTypes.swift @@ -0,0 +1,69 @@ +@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]] + +@JS func processJSObjectArray(_ objects: [JSObject]) -> [JSObject] +@JS func processOptionalJSObjectArray(_ objects: [JSObject?]) -> [JSObject?] +@JS func processNestedJSObjectArray(_ objects: [[JSObject]]) -> [[JSObject]] + +@JSFunction func checkArray(_ a: JSObject) throws(JSException) -> Void +@JSFunction func checkArrayWithLength(_ a: JSObject, _ b: Double) throws(JSException) -> Void + +@JSFunction func importProcessNumbers(_ values: [Double]) throws(JSException) -> Void +@JSFunction func importGetNumbers() throws(JSException) -> [Double] +@JSFunction func importTransformNumbers(_ values: [Double]) throws(JSException) -> [Double] +@JSFunction func importProcessStrings(_ values: [String]) throws(JSException) -> [String] +@JSFunction func importProcessBooleans(_ values: [Bool]) throws(JSException) -> [Bool] diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Async.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Async.swift similarity index 100% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Async.swift rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Async.swift diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/DefaultParameters.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/DefaultParameters.swift new file mode 100644 index 000000000..08dcde096 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/DefaultParameters.swift @@ -0,0 +1,87 @@ +@JS public func testStringDefault(message: String = "Hello World") -> String + +@JS public func testNegativeIntDefault(value: Int = -42) -> Int + +@JS public func testBoolDefault(flag: Bool = true) -> Bool + +@JS public func testNegativeFloatDefault(temp: Float = -273.15) -> Float + +@JS public func testDoubleDefault(precision: Double = 2.718) -> Double + +@JS public func testOptionalDefault(name: String? = nil) -> String? + +@JS public func testOptionalStringDefault(greeting: String? = "Hi") -> String? + +@JS public func testMultipleDefaults( + title: String = "Default Title", + count: Int = 10, + enabled: Bool = false +) -> String + +@JS public enum Status { + case active + case inactive + case pending +} + +@JS public func testEnumDefault(status: Status = .active) -> Status + +@JS class DefaultGreeter { + @JS var name: String + @JS init(name: String) +} + +@JS class EmptyGreeter { + @JS init() +} + +@JS public func testComplexInit(greeter: DefaultGreeter = DefaultGreeter(name: "DefaultUser")) -> DefaultGreeter +@JS public func testEmptyInit(greeter: EmptyGreeter = EmptyGreeter()) -> EmptyGreeter + +@JS class ConstructorDefaults { + @JS var name: String + @JS var count: Int + @JS var enabled: Bool + @JS var status: Status + @JS var tag: String? + + @JS init( + name: String = "Default", + count: Int = 42, + enabled: Bool = true, + status: Status = .active, + tag: String? = nil + ) +} + +@JS struct Config { + var name: String + var value: Int + var enabled: Bool +} + +@JS public func testOptionalStructDefault(point: Config? = nil) -> Config? +@JS public func testOptionalStructWithValueDefault( + point: Config? = Config(name: "default", value: 42, enabled: true) +) -> Config? + +@JS struct MathOperations { + var baseValue: Double + + @JS init(baseValue: Double = 0.0) + @JS func add(a: Double, b: Double = 10.0) -> Double + @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/MacroSwift/DictionaryTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/DictionaryTypes.swift new file mode 100644 index 000000000..c699ea79b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/DictionaryTypes.swift @@ -0,0 +1,15 @@ +@JS class Box { + var value: Int + + init(value: Int) { + self.value = value + } +} + +@JS func mirrorDictionary(_ values: [String: Int]) -> [String: Int] +@JS func optionalDictionary(_ values: [String: String]?) -> [String: String]? +@JS func nestedDictionary(_ values: [String: [Int]]) -> [String: [Int]] +@JS func boxDictionary(_ boxes: [String: Box]) -> [String: Box] +@JS func optionalBoxDictionary(_ boxes: [String: Box?]) -> [String: Box?] + +@JSFunction func importMirrorDictionary(_ values: [String: Double]) throws(JSException) -> [String: Double] diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumAssociatedValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumAssociatedValue.swift new file mode 100644 index 000000000..a0e6cbfeb --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumAssociatedValue.swift @@ -0,0 +1,120 @@ +@JS +enum APIResult { + case success(String) + case failure(Int) + case flag(Bool) + case rate(Float) + case precise(Double) + case info +} + +@JS func handle(result: APIResult) +@JS func getResult() -> APIResult +@JS func roundtripAPIResult(result: APIResult) -> APIResult +@JS func roundTripOptionalAPIResult(result: APIResult?) -> APIResult? + +@JS +enum ComplexResult { + case success(String) + case error(String, Int) + case status(Bool, Int, String) + case coordinates(Double, Double, Double) + case comprehensive(Bool, Bool, Int, Int, Double, Double, String, String, String) + case info +} + +@JS func handleComplex(result: ComplexResult) +@JS func getComplexResult() -> ComplexResult +@JS func roundtripComplexResult(_ result: ComplexResult) -> ComplexResult +@JS func roundTripOptionalComplexResult(result: ComplexResult?) -> ComplexResult? + +@JS +enum Utilities { + @JS enum Result { + case success(String) + case failure(String, Int) + case status(Bool, Int, String) + } +} + +@JS func roundTripOptionalUtilitiesResult(result: Utilities.Result?) -> Utilities.Result? + +@JS(namespace: "API") +@JS enum NetworkingResult { + case success(String) + case failure(String, Int) +} + +@JS func roundTripOptionalNetworkingResult(result: NetworkingResult?) -> NetworkingResult? + +@JS +enum APIOptionalResult { + case success(String?) + case failure(Int?, Bool?) + case status(Bool?, Int?, String?) +} +@JS func roundTripOptionalAPIOptionalResult(result: APIOptionalResult?) -> APIOptionalResult? +@JS func compareAPIResults(result1: APIOptionalResult?, result2: APIOptionalResult?) -> APIOptionalResult? + +@JS enum Precision: Float { + case rough = 0.1 + case fine = 0.001 +} + +@JS enum CardinalDirection { + case north + case south + case east + case west +} + +@JS +enum TypedPayloadResult { + case precision(Precision) + case direction(CardinalDirection) + case optPrecision(Precision?) + case optDirection(CardinalDirection?) + case empty +} + +@JS func roundTripTypedPayloadResult(_ result: TypedPayloadResult) -> TypedPayloadResult +@JS func roundTripOptionalTypedPayloadResult(_ result: TypedPayloadResult?) -> TypedPayloadResult? + +@JS struct Point { + var x: Double + var y: Double +} + +@JS class User { + var name: String + + init(name: String) { + self.name = name + } +} + +@JS +enum AllTypesResult { + case structPayload(Point) + case classPayload(User) + case jsObjectPayload(JSObject) + case nestedEnum(APIResult) + case arrayPayload([Int]) + case empty +} + +@JS func roundTripAllTypesResult(_ result: AllTypesResult) -> AllTypesResult +@JS func roundTripOptionalAllTypesResult(_ result: AllTypesResult?) -> AllTypesResult? + +@JS +enum OptionalAllTypesResult { + case optStruct(Point?) + case optClass(User?) + case optJSObject(JSObject?) + case optNestedEnum(APIResult?) + case optArray([Int]?) + case empty +} + +@JS func roundTripOptionalPayloadResult(_ result: OptionalAllTypesResult) -> OptionalAllTypesResult +@JS func roundTripOptionalPayloadResultOpt(_ result: OptionalAllTypesResult?) -> OptionalAllTypesResult? diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumCase.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumCase.swift new file mode 100644 index 000000000..c54ee6aeb --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumCase.swift @@ -0,0 +1,32 @@ +@JS enum Direction { + case north + case south + case east + case west +} + +@JS enum Status { + case loading + case success + case error +} + +@JS func setDirection(_ direction: Direction) +@JS func getDirection() -> Direction +@JS func processDirection(_ input: Direction) -> Status +@JS func roundTripOptionalDirection(_ input: Direction?) -> Direction? + +@JS(enumStyle: .tsEnum) enum TSDirection { + case north + case south + case east + case west +} + +@JS func setTSDirection(_ direction: TSDirection) +@JS func getTSDirection() -> TSDirection +@JS func roundTripOptionalTSDirection(_ input: TSDirection?) -> TSDirection? + +@JS public enum PublicStatus { + case success +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumNamespace.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumNamespace.swift new file mode 100644 index 000000000..dbf044834 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumNamespace.swift @@ -0,0 +1,69 @@ +// Empty enums to act as namespace wrappers for nested elements + +@JS enum Utils { + @JS class Converter { + @JS init() {} + + @JS func toString(value: Int) -> String { + return String(value) + } + } +} + +@JS enum Networking { + @JS enum API { + @JS enum Method { + case get + case post + case put + case delete + } + // Invalid to declare @JS(namespace) here as it would be conflicting with nesting + @JS class HTTPServer { + @JS init() {} + @JS func call(_ method: Method) {} + } + } +} + +@JS enum Configuration { + @JS enum LogLevel: String { + case debug = "debug" + case info = "info" + case warning = "warning" + case error = "error" + } + + @JS enum Port: Int { + case http = 80 + case https = 443 + case development = 3000 + } +} + +@JS(namespace: "Networking.APIV2") +enum Internal { + @JS enum SupportedMethod { + case get + case post + } + @JS class TestServer { + @JS init() {} + @JS func call(_ method: SupportedMethod) {} + } +} + +@JS(namespace: "Services.Graph") +enum GraphOperations { + @JS static func createGraph(rootId: Int) -> Int { + return rootId * 10 + } + + @JS static func nodeCount(graphId: Int) -> Int { + return graphId + } + + @JS static func validate(graphId: Int) throws(JSException) -> Bool { + return graphId > 0 + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumRawType.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumRawType.swift new file mode 100644 index 000000000..6e18c913c --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumRawType.swift @@ -0,0 +1,136 @@ +@JS enum Theme: String { + case light = "light" + case dark = "dark" + case auto = "auto" +} + +@JS(enumStyle: .tsEnum) enum TSTheme: String { + case light = "light" + case dark = "dark" + case auto = "auto" +} + +@JS enum FeatureFlag: Bool { + case enabled = true + case disabled = false +} + +@JS enum HttpStatus: Int { + case ok = 200 + case notFound = 404 + case serverError = 500 +} + +@JS(enumStyle: .tsEnum) enum TSHttpStatus: Int { + case ok = 200 + case notFound = 404 + case serverError = 500 +} + +@JS enum Priority: Int32 { + case lowest = -1 + case low = 2 + case medium = 3 + case high = 4 + case highest = 5 +} + +@JS enum FileSize: Int64 { + case tiny = 1024 + case small = 10240 + case medium = 102400 + case large = 1048576 +} + +@JS enum UserId: UInt { + case guest = 0 + case user = 1000 + case admin = 9999 +} + +@JS enum TokenId: UInt32 { + case invalid = 0 + case session = 12345 + case refresh = 67890 +} + +@JS enum SessionId: UInt64 { + case none = 0 + case active = 9876543210 + case expired = 1234567890 +} + +@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 + case pi = 3.14159 +} + +@JS func setTheme(_ theme: Theme) +@JS func getTheme() -> Theme +@JS func roundTripOptionalTheme(_ input: Theme?) -> Theme? + +@JS func setTSTheme(_ theme: TSTheme) +@JS func getTSTheme() -> TSTheme +@JS func roundTripOptionalTSTheme(_ input: TSTheme?) -> TSTheme? + +@JS func setFeatureFlag(_ flag: FeatureFlag) +@JS func getFeatureFlag() -> FeatureFlag +@JS func roundTripOptionalFeatureFlag(_ input: FeatureFlag?) -> FeatureFlag? + +@JS func setHttpStatus(_ status: HttpStatus) +@JS func getHttpStatus() -> HttpStatus +@JS func roundTripOptionalHttpStatus(_ input: HttpStatus?) -> HttpStatus? + +@JS func setTSHttpStatus(_ status: TSHttpStatus) +@JS func getTSHttpStatus() -> TSHttpStatus +@JS func roundTripOptionalHttpStatus(_ input: TSHttpStatus?) -> TSHttpStatus? + +@JS func setPriority(_ priority: Priority) +@JS func getPriority() -> Priority +@JS func roundTripOptionalPriority(_ input: Priority?) -> Priority? + +@JS func setFileSize(_ size: FileSize) +@JS func getFileSize() -> FileSize +@JS func roundTripOptionalFileSize(_ input: FileSize?) -> FileSize? + +@JS func setUserId(_ id: UserId) +@JS func getUserId() -> UserId +@JS func roundTripOptionalUserId(_ input: UserId?) -> UserId? + +@JS func setTokenId(_ token: TokenId) +@JS func getTokenId() -> TokenId +@JS func roundTripOptionalTokenId(_ input: TokenId?) -> TokenId? + +@JS func setSessionId(_ session: SessionId) +@JS func getSessionId() -> SessionId +@JS func roundTripOptionalSessionId(_ input: SessionId?) -> SessionId? + +@JS func setPrecision(_ precision: Precision) +@JS func getPrecision() -> Precision +@JS func roundTripOptionalPrecision(_ input: Precision?) -> Precision? + +@JS func setRatio(_ ratio: Ratio) +@JS func getRatio() -> Ratio +@JS func roundTripOptionalRatio(_ input: Ratio?) -> Ratio? + +@JS func processTheme(_ theme: Theme) -> HttpStatus +@JS func convertPriority(_ status: HttpStatus) -> Priority +@JS func validateSession(_ session: SessionId) -> Theme + +enum FeatureFlag: String { + case foo = "foo" + case bar = "bar" +} +extension FeatureFlag: _BridgedSwiftEnumNoPayload {} + +@JSFunction func takesFeatureFlag(_ flag: FeatureFlag) throws(JSException) -> Void + +@JSFunction func returnsFeatureFlag() throws(JSException) -> FeatureFlag diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/GlobalGetter.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/GlobalGetter.swift new file mode 100644 index 000000000..fe3f7b068 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/GlobalGetter.swift @@ -0,0 +1,6 @@ +@JSClass +struct JSConsole { + @JSFunction func log(_ message: String) throws(JSException) +} + +@JSGetter var console: JSConsole diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/GlobalThisImports.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/GlobalThisImports.swift new file mode 100644 index 000000000..fbf77adf1 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/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/Inputs/MacroSwift/ImportArray.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/ImportArray.swift new file mode 100644 index 000000000..cd9142a26 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/ImportArray.swift @@ -0,0 +1,2 @@ +@JSFunction func roundtrip(_ items: [Int]) throws(JSException) -> [Int] +@JSFunction func logStrings(_ items: [String]) throws(JSException) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/ImportedTypeInExportedInterface.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/ImportedTypeInExportedInterface.swift new file mode 100644 index 000000000..db167c5a9 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/ImportedTypeInExportedInterface.swift @@ -0,0 +1,17 @@ +@JSClass class Foo { + @JSFunction init() throws(JSException) +} + +@JS func makeFoo() throws(JSException) -> Foo { + return try Foo() +} + +@JS func processFooArray(_ foos: [Foo]) -> [Foo] +@JS func processOptionalFooArray(_ foos: [Foo?]) -> [Foo?] + +@JS struct FooContainer { + var foo: Foo + var optionalFoo: Foo? +} + +@JS func roundtripFooContainer(_ container: FooContainer) -> FooContainer diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/InvalidPropertyNames.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/InvalidPropertyNames.swift new file mode 100644 index 000000000..ea5755dec --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/InvalidPropertyNames.swift @@ -0,0 +1,29 @@ +@JSFunction func createWeirdObject() throws(JSException) -> WeirdNaming + +@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/Inputs/MacroSwift/JSClass.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/JSClass.swift new file mode 100644 index 000000000..6459f5354 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/JSClass.swift @@ -0,0 +1,15 @@ +@JSClass struct Greeter { + @JSGetter var name: String + @JSSetter func setName(_ value: String) throws(JSException) + @JSGetter var age: Double + @JSFunction init(_ name: String) throws(JSException) + @JSFunction func greet() throws(JSException) -> String + @JSFunction func changeName(_ name: String) throws(JSException) -> Void +} + +@JSFunction func returnAnimatable() throws(JSException) -> Animatable + +@JSClass struct Animatable { + @JSFunction func animate(_ keyframes: JSObject, _ options: JSObject) throws(JSException) -> JSObject + @JSFunction func getAnimations(_ options: JSObject) throws(JSException) -> JSObject +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/JSClassStaticFunctions.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/JSClassStaticFunctions.swift new file mode 100644 index 000000000..c64952565 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/JSClassStaticFunctions.swift @@ -0,0 +1,12 @@ +@JSClass struct StaticBox { + @JSFunction static func create(_ value: Double) throws(JSException) -> StaticBox + @JSFunction func value() throws(JSException) -> Double + @JSFunction static func value() throws(JSException) -> Double + @JSFunction static func makeDefault() throws(JSException) -> StaticBox + @JSFunction(jsName: "with-dashes") static func dashed() throws(JSException) -> StaticBox +} + +@JSClass struct WithCtor { + @JSFunction init(_ value: Double) throws(JSException) + @JSFunction static func create(_ value: Double) throws(JSException) -> WithCtor +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/JSValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/JSValue.swift new file mode 100644 index 000000000..2a34f5f2b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/JSValue.swift @@ -0,0 +1,41 @@ +@JS func roundTripJSValue(_ value: JSValue) -> JSValue { + return value +} + +@JS func roundTripOptionalJSValue(_ value: JSValue?) -> JSValue? { + return value +} + +@JS func roundTripJSValueArray(_ values: [JSValue]) -> [JSValue] { + return values +} + +@JS func roundTripOptionalJSValueArray(_ values: [JSValue]?) -> [JSValue]? { + return values +} + +@JS class JSValueHolder { + @JS var value: JSValue + @JS var optionalValue: JSValue? + + @JS init(value: JSValue, optionalValue: JSValue?) { + self.value = value + self.optionalValue = optionalValue + } + + @JS func update(value: JSValue, optionalValue: JSValue?) { + self.value = value + self.optionalValue = optionalValue + } + + @JS func echo(value: JSValue) -> JSValue { + return value + } + + @JS func echoOptional(_ value: JSValue?) -> JSValue? { + return value + } +} + +@JSFunction func jsEchoJSValue(_ value: JSValue) throws(JSException) -> JSValue +@JSFunction func jsEchoJSValueArray(_ values: [JSValue]) throws(JSException) -> [JSValue] diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/MixedGlobal.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/MixedGlobal.swift new file mode 100644 index 000000000..f65abe3a7 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/MixedGlobal.swift @@ -0,0 +1,8 @@ +@JS(namespace: "GlobalAPI") +func globalFunction() -> String + +@JS(namespace: "GlobalAPI") +class GlobalClass { + @JS public init() + @JS public func greet() -> String +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/MixedPrivate.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/MixedPrivate.swift new file mode 100644 index 000000000..0f99fcede --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/MixedPrivate.swift @@ -0,0 +1,8 @@ +@JS(namespace: "PrivateAPI") +func privateFunction() -> String + +@JS(namespace: "PrivateAPI") +class PrivateClass { + @JS public init() + @JS public func greet() -> String +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/CrossFileClassA.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/CrossFileClassA.swift new file mode 100644 index 000000000..a26cae313 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/CrossFileClassA.swift @@ -0,0 +1,3 @@ +@JS class ClassA { + @JS var linkedB: ClassB? +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/CrossFileClassB.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/CrossFileClassB.swift new file mode 100644 index 000000000..c7c5b80d9 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/CrossFileClassB.swift @@ -0,0 +1,3 @@ +@JS class ClassB { + @JS init() {} +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/CrossFileFunctionA.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/CrossFileFunctionA.swift new file mode 100644 index 000000000..9a2929e8e --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/CrossFileFunctionA.swift @@ -0,0 +1,18 @@ +@JS class FunctionA { + @JS init() {} + + // Method that takes a cross-file type as parameter + @JS func processB(b: FunctionB) -> String { + return "Processed \(b.value)" + } + + // Method that returns a cross-file type + @JS func createB(value: String) -> FunctionB { + return FunctionB(value: value) + } +} + +// Standalone function that uses cross-file types +@JS func standaloneFunction(b: FunctionB) -> FunctionB { + return b +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/CrossFileFunctionB.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/CrossFileFunctionB.swift new file mode 100644 index 000000000..9c1828219 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/CrossFileFunctionB.swift @@ -0,0 +1,7 @@ +@JS class FunctionB { + @JS var value: String + + @JS init(value: String) { + self.value = value + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/ExportedOnly.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/ExportedOnly.swift new file mode 100644 index 000000000..d7887d2bd --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/ExportedOnly.swift @@ -0,0 +1,3 @@ +struct ExportedOnly { + let value: Int = 0 +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/ImportedFunctions.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/ImportedFunctions.swift new file mode 100644 index 000000000..451424777 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Multifile/ImportedFunctions.swift @@ -0,0 +1 @@ +@JSFunction func fetchNumber() throws(JSException) -> Int diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Namespaces.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Namespaces.swift similarity index 100% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Namespaces.swift rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Namespaces.swift diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Optionals.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Optionals.swift new file mode 100644 index 000000000..57d994519 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Optionals.swift @@ -0,0 +1,128 @@ +@JS class Greeter { + @JS var name: String? + + @JS init(name: String?) { + self.name = name + } + + @JS func greet() -> String { + return "Hello, " + (self.name ?? "stranger") + "!" + } + + @JS func changeName(name: String?) { + self.name = name + } +} + +@JS +func roundTripOptionalClass(value: Greeter?) -> Greeter? { + return value +} + +@JS +class OptionalPropertyHolder { + @JS var optionalName: String? = nil + @JS var optionalAge: Int? = nil + @JS var optionalGreeter: Greeter? = nil + + @JS init() {} +} + +@JS func testOptionalPropertyRoundtrip(_ holder: OptionalPropertyHolder?) -> OptionalPropertyHolder? + +@JS +func roundTripString(name: String?) -> String? { + return name +} + +@JS +func roundTripInt(value: Int?) -> Int? { + return value +} + +@JS +func roundTripBool(flag: Bool?) -> Bool? { + return flag +} + +@JS +func roundTripFloat(number: Float?) -> Float? { + return number +} + +@JS +func roundTripDouble(precision: Double?) -> Double? { + return precision +} + +@JS func roundTripSyntax(name: Optional) -> Optional { + return name +} + +@JS func roundTripMixSyntax(name: String?) -> Optional { + return name +} + +@JS func roundTripSwiftSyntax(name: Swift.Optional) -> Swift.Optional { + return name +} + +@JS func roundTripMixedSwiftSyntax(name: String?) -> Swift.Optional { + return name +} + +@JS func roundTripWithSpaces(value: Optional) -> Optional { + return value +} + +typealias OptionalAge = Int? + +@JS func roundTripAlias(age: OptionalAge) -> OptionalAge { + return age +} + +typealias OptionalNameAlias = Optional +@JS func roundTripOptionalAlias(name: OptionalNameAlias) -> OptionalNameAlias { + return name +} + +@JS +func testMixedOptionals(firstName: String?, lastName: String?, age: Int?, active: Bool) -> String? { + return nil +} + +@JSClass struct WithOptionalJSClass { + @JSFunction init(valueOrNull: String?, valueOrUndefined: JSUndefinedOr) throws(JSException) + + @JSGetter var stringOrNull: String? + @JSSetter func setStringOrNull(_ value: String?) throws(JSException) + @JSGetter var stringOrUndefined: JSUndefinedOr + @JSSetter func setStringOrUndefined(_ value: JSUndefinedOr) throws(JSException) + @JSFunction func roundTripStringOrNull(value: String?) throws(JSException) -> String? + @JSFunction func roundTripStringOrUndefined( + value: JSUndefinedOr + ) throws(JSException) -> JSUndefinedOr + + @JSGetter var doubleOrNull: Double? + @JSSetter func setDoubleOrNull(_ value: Double?) throws(JSException) + @JSGetter var doubleOrUndefined: JSUndefinedOr + @JSSetter func setDoubleOrUndefined(_ value: JSUndefinedOr) throws(JSException) + @JSFunction func roundTripDoubleOrNull(value: Double?) throws(JSException) -> Double? + @JSFunction func roundTripDoubleOrUndefined( + value: JSUndefinedOr + ) throws(JSException) -> JSUndefinedOr + + @JSGetter var boolOrNull: Bool? + @JSSetter func setBoolOrNull(_ value: Bool?) throws(JSException) + @JSGetter var boolOrUndefined: JSUndefinedOr + @JSSetter func setBoolOrUndefined(_ value: JSUndefinedOr) throws(JSException) + @JSFunction func roundTripBoolOrNull(value: Bool?) throws(JSException) -> Bool? + @JSFunction func roundTripBoolOrUndefined(value: JSUndefinedOr) throws(JSException) -> JSUndefinedOr + + @JSGetter var intOrNull: Int? + @JSSetter func setIntOrNull(_ value: Int?) throws(JSException) + @JSGetter var intOrUndefined: JSUndefinedOr + @JSSetter func setIntOrUndefined(_ value: JSUndefinedOr) throws(JSException) + @JSFunction func roundTripIntOrNull(value: Int?) throws(JSException) -> Int? + @JSFunction func roundTripIntOrUndefined(value: JSUndefinedOr) throws(JSException) -> JSUndefinedOr +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/PrimitiveParameters.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/PrimitiveParameters.swift new file mode 100644 index 000000000..97495d947 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/PrimitiveParameters.swift @@ -0,0 +1,2 @@ +@JS func check(a: Int, b: UInt, c: Float, d: Double, e: Bool) {} +@JSFunction func check(_ a: Double, _ b: Bool) throws(JSException) -> Void diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/PrimitiveReturn.swift similarity index 52% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveReturn.swift rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/PrimitiveReturn.swift index 96a5dbc3c..d2a65faef 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveReturn.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/PrimitiveReturn.swift @@ -1,4 +1,8 @@ @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() } + +@JSFunction func checkNumber() throws(JSException) -> Double +@JSFunction func checkBoolean() throws(JSException) -> Bool diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/PropertyTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/PropertyTypes.swift new file mode 100644 index 000000000..684825017 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/PropertyTypes.swift @@ -0,0 +1,97 @@ +@JS class PropertyHolder { + // Primitive properties + @JS var intValue: Int + @JS var floatValue: Float + @JS var doubleValue: Double + @JS var boolValue: Bool + @JS var stringValue: String + + // Readonly primitive properties + @JS let readonlyInt: Int = 42 + @JS let readonlyFloat: Float = 3.14 + @JS let readonlyDouble: Double = 2.718281828 + @JS let readonlyBool: Bool = true + @JS let readonlyString: String = "constant" + + // JSObject property + @JS var jsObject: JSObject + + // SwiftHeapObject property (will be set later) + @JS var sibling: PropertyHolder + + // Lazy stored property - should this be supported or generate an error? + @JS lazy var lazyValue: String = "computed lazily" + + // Computed property with getter only (readonly) + @JS var computedReadonly: Int { + return intValue * 2 + } + + // Computed property with getter and setter + @JS var computedReadWrite: String { + get { + return "Value: \(intValue)" + } + set { + // Parse the number from "Value: X" format + if let range = newValue.range(of: "Value: "), + let number = Int(String(newValue[range.upperBound...])) + { + intValue = number + } + } + } + + // Property with property observers + @JS var observedProperty: Int { + willSet { + print("Will set to \(newValue)") + } + didSet { + print("Did set from \(oldValue)") + } + } + + @JS init( + intValue: Int, + floatValue: Float, + doubleValue: Double, + boolValue: Bool, + stringValue: String, + jsObject: JSObject + ) { + self.intValue = intValue + self.floatValue = floatValue + self.doubleValue = doubleValue + self.boolValue = boolValue + self.stringValue = stringValue + self.jsObject = jsObject + self.sibling = self + } + + @JS func getAllValues() -> String { + return "int:\(intValue),float:\(floatValue),double:\(doubleValue),bool:\(boolValue),string:\(stringValue)" + } +} + +@JS func createPropertyHolder( + intValue: Int, + floatValue: Float, + doubleValue: Double, + boolValue: Bool, + stringValue: String, + jsObject: JSObject +) -> PropertyHolder { + return PropertyHolder( + intValue: intValue, + floatValue: floatValue, + doubleValue: doubleValue, + boolValue: boolValue, + stringValue: stringValue, + jsObject: jsObject + ) +} + +@JS func testPropertyHolder(holder: PropertyHolder) -> String { + return holder.getAllValues() +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Protocol.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Protocol.swift new file mode 100644 index 000000000..fbbad0615 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Protocol.swift @@ -0,0 +1,116 @@ +import JavaScriptKit + +@JS enum Direction { + case north + case south + case east + case west +} + +@JS enum ExampleEnum: String { + case test = "test" + case test2 = "test2" +} + +@JS enum Result { + case success(String) + case failure(Int) +} + +@JS enum Priority: Int { + case low = -1 + case medium = 0 + case high = 1 +} + +@JS class Helper { + @JS var value: Int + + @JS init(value: Int) { + self.value = value + } + + @JS func increment() { + value += 1 + } +} + +@JS protocol MyViewControllerDelegate { + var eventCount: Int { get set } + var delegateName: String { get } + var optionalName: String? { get set } + var optionalRawEnum: ExampleEnum? { get set } + var rawStringEnum: ExampleEnum { get set } + var result: Result { get set } + var optionalResult: Result? { get set } + var direction: Direction { get set } + var directionOptional: Direction? { get set } + var priority: Priority { get set } + var priorityOptional: Priority? { get set } + func onSomethingHappened() + func onValueChanged(_ value: String) + func onCountUpdated(count: Int) -> Bool + func onLabelUpdated(_ prefix: String, _ suffix: String) + func isCountEven() -> Bool + func onHelperUpdated(_ helper: Helper) + func createHelper() -> Helper + func onOptionalHelperUpdated(_ helper: Helper?) + func createOptionalHelper() -> Helper? + func createEnum() -> ExampleEnum + func handleResult(_ result: Result) + func getResult() -> Result +} + +@JS class MyViewController { + @JS + var delegate: MyViewControllerDelegate + + @JS + var secondDelegate: MyViewControllerDelegate? + + @JS init(delegate: MyViewControllerDelegate) { + self.delegate = delegate + } + + @JS func triggerEvent() { + delegate.onSomethingHappened() + } + + @JS func updateValue(_ value: String) { + delegate.onValueChanged(value) + } + + @JS func updateCount(_ count: Int) -> Bool { + return delegate.onCountUpdated(count: count) + } + + @JS func updateLabel(_ prefix: String, _ suffix: String) { + delegate.onLabelUpdated(prefix, suffix) + } + + @JS func checkEvenCount() -> Bool { + return delegate.isCountEven() + } + + @JS func sendHelper(_ helper: Helper) { + 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/MacroSwift/StaticFunctions.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/StaticFunctions.swift new file mode 100644 index 000000000..1d42cf415 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/StaticFunctions.swift @@ -0,0 +1,40 @@ +@JS class MathUtils { + @JS init() {} + + @JS class func subtract(a: Int, b: Int) -> Int { + return a - b + } + + @JS static func add(a: Int, b: Int) -> Int { + return a + b + } + + @JS func multiply(x: Int, y: Int) -> Int { + return x * y + } +} + +@JS enum Calculator { + case scientific + case basic + + @JS static func square(value: Int) -> Int { + return value * value + } +} + +@JS +enum APIResult { + case success(String) + case failure(Int) + + @JS static func roundtrip(value: APIResult) -> APIResult {} +} + +@JS enum Utils { + @JS enum String { + @JS static func uppercase(_ text: String) -> String { + return text.uppercased() + } + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/StaticProperties.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/StaticProperties.swift new file mode 100644 index 000000000..1a89b55c5 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/StaticProperties.swift @@ -0,0 +1,42 @@ +@JS class PropertyClass { + @JS init() {} + + @JS static let staticConstant: String = "constant" + @JS static var staticVariable: Int = 42 + @JS static var jsObjectProperty: JSObject = JSObject() + @JS class var classVariable: String = "overridable" + + @JS static var computedProperty: String { + get { return "\(staticVariable) computed" } + set { staticVariable = newValue + 5 } + } + + @JS static var readOnlyComputed: Int { + return 100 + } + + @JS static var optionalProperty: String? = nil +} + +@JS enum PropertyEnum { + case value1 + case value2 + + @JS static var enumProperty: String = "enum value" + @JS static let enumConstant: Int = 42 + @JS static var computedEnum: String { + get { return enumProperty + " computed" } + set { enumProperty = newValue + " computed" } + } +} + +@JS enum PropertyNamespace { + @JS static var namespaceProperty: String = "namespace" + @JS static let namespaceConstant: String = "constant" + + @JS enum Nested { + @JS nonisolated(unsafe) static var nestedProperty: Int = 999 + @JS static let nestedConstant: String = "nested" + @JS nonisolated(unsafe) static var nestedDouble: Double = 1.414 + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/StringParameter.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/StringParameter.swift new file mode 100644 index 000000000..32fc62f32 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/StringParameter.swift @@ -0,0 +1,5 @@ +@JS func checkString(a: String) {} +@JS func roundtripString(a: String) -> String { return a } + +@JSFunction func checkString(_ a: String) throws(JSException) -> Void +@JSFunction func checkStringWithLength(_ a: String, _ b: Double) throws(JSException) -> Void diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/StringReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/StringReturn.swift new file mode 100644 index 000000000..4b5bc088a --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/StringReturn.swift @@ -0,0 +1,2 @@ +@JS func checkString() -> String { fatalError() } +@JSFunction func checkString() throws(JSException) -> String diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/SwiftClass.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClass.swift similarity index 52% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/SwiftClass.swift rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClass.swift index a803504f9..d7b5a5b8e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/SwiftClass.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClass.swift @@ -1,5 +1,5 @@ @JS class Greeter { - var name: String + @JS var name: String @JS init(name: String) { self.name = name @@ -15,3 +15,9 @@ @JS func takeGreeter(greeter: Greeter) { print(greeter.greet()) } + +@JS public class PublicGreeter {} +@JS package class PackageGreeter {} + +@JSFunction func jsRoundTripGreeter(greeter: Greeter) throws(JSException) -> Greeter +@JSFunction func jsRoundTripOptionalGreeter(greeter: Greeter?) throws(JSException) -> Greeter? diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClosure.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClosure.swift new file mode 100644 index 000000000..791b1b7a9 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClosure.swift @@ -0,0 +1,68 @@ +import JavaScriptKit + +@JS public class Person { + public let name: String + + @JS public init(name: String) { + self.name = name + } +} + +@JS class TestProcessor { + @JS init(transform: @escaping (String) -> String) {} +} + +@JS func roundtripString(_ stringClosure: (String) -> String) -> (String) -> String +@JS func roundtripInt(_ intClosure: (Int) -> Int) -> (Int) -> Int +@JS func roundtripBool(_ boolClosure: (Bool) -> Bool) -> (Bool) -> Bool +@JS func roundtripFloat(_ floatClosure: (Float) -> Float) -> (Float) -> Float +@JS func roundtripDouble(_ doubleClosure: (Double) -> Double) -> (Double) -> Double + +@JS func roundtripOptionalString(_ stringClosure: (String?) -> String?) -> (String?) -> String? +@JS func roundtripOptionalInt(_ intClosure: (Int?) -> Int?) -> (Int?) -> Int? +@JS func roundtripOptionalBool(_ boolClosure: (Bool?) -> Bool?) -> (Bool?) -> Bool? +@JS func roundtripOptionalFloat(_ floatClosure: (Float?) -> Float?) -> (Float?) -> Float? +@JS func roundtripOptionalDouble(_ doubleClosure: (Double?) -> Double?) -> (Double?) -> Double? + +@JS func roundtripPerson(_ personClosure: (Person) -> Person) -> (Person) -> Person +@JS func roundtripOptionalPerson(_ personClosure: (Person?) -> Person?) -> (Person?) -> Person? + +@JS func roundtripDirection(_ callback: (Direction) -> Direction) -> (Direction) -> Direction +@JS func roundtripTheme(_ callback: (Theme) -> Theme) -> (Theme) -> Theme +@JS func roundtripHttpStatus(_ callback: (HttpStatus) -> HttpStatus) -> (HttpStatus) -> HttpStatus +@JS func roundtripAPIResult(_ callback: (APIResult) -> APIResult) -> (APIResult) -> APIResult + +@JS func roundtripOptionalDirection(_ callback: (Direction?) -> Direction?) -> (Direction?) -> Direction? +@JS func roundtripOptionalTheme(_ callback: (Theme?) -> Theme?) -> (Theme?) -> Theme? +@JS func roundtripOptionalHttpStatus(_ callback: (HttpStatus?) -> HttpStatus?) -> (HttpStatus?) -> HttpStatus? +@JS func roundtripOptionalAPIResult(_ callback: (APIResult?) -> APIResult?) -> (APIResult?) -> APIResult? +@JS func roundtripOptionalDirection(_ callback: (Direction?) -> Direction?) -> (Direction?) -> Direction? + +@JS enum Direction { + case north + case south + case east + case west +} + +@JS enum Theme: String { + case light = "light" + case dark = "dark" + case auto = "auto" +} + +@JS enum HttpStatus: Int { + case ok = 200 + case notFound = 404 + case serverError = 500 + case unknown = -1 +} + +@JS enum APIResult { + case success(String) + case failure(Int) + case flag(Bool) + case rate(Float) + case precise(Double) + case info +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClosureImports.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClosureImports.swift new file mode 100644 index 000000000..d9f92fffb --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClosureImports.swift @@ -0,0 +1,3 @@ +@JSFunction func applyInt(_ value: Int, _ transform: (Int) -> Int) throws(JSException) -> Int + +@JSFunction func makeAdder(_ base: Int) throws(JSException) -> (Int) -> Int diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftStruct.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftStruct.swift new file mode 100644 index 000000000..0d84f4736 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftStruct.swift @@ -0,0 +1,62 @@ +@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?) +} + +@JS struct Address { + var street: String + var city: String + var zipCode: Int? +} + +@JS struct Person { + var name: String + var age: Int + var address: Address + var email: String? +} + +@JS class Greeter { + @JS var name: String + + @JS init(name: String) + @JS func greet() -> String +} + +@JS struct Session { + var id: Int + var owner: Greeter +} + +@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" + @JS nonisolated(unsafe) static var timeout: Double = 30.0 + @JS static var computedSetting: String { "Config: \(defaultConfig)" } + @JS static func update(_ timeout: Double) -> Double +} + +@JS struct Container { + var object: JSObject + var optionalObject: JSObject? +} + +@JS func roundtripContainer(_ container: Container) -> Container diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftStructImports.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftStructImports.swift new file mode 100644 index 000000000..b00fd768a --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/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/Throws.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Throws.swift similarity index 100% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Throws.swift rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Throws.swift diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/UnsafePointer.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/UnsafePointer.swift new file mode 100644 index 000000000..eb6ca0071 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/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/Inputs/MacroSwift/VoidParameterVoidReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/VoidParameterVoidReturn.swift new file mode 100644 index 000000000..4b9cd0d02 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/VoidParameterVoidReturn.swift @@ -0,0 +1,2 @@ +@JS func check() {} +@JSFunction func check() throws(JSException) -> Void diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveParameters.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveParameters.swift deleted file mode 100644 index 62e780083..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/PrimitiveParameters.swift +++ /dev/null @@ -1 +0,0 @@ -@JS func check(a: Int, b: Float, c: Double, d: Bool) {} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringParameter.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringParameter.swift deleted file mode 100644 index e6763d4cd..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringParameter.swift +++ /dev/null @@ -1 +0,0 @@ -@JS func checkString(a: String) {} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringReturn.swift deleted file mode 100644 index fe070f0db..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringReturn.swift +++ /dev/null @@ -1 +0,0 @@ -@JS func checkString() -> String { fatalError() } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/VoidParameterVoidReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/VoidParameterVoidReturn.swift deleted file mode 100644 index ba0cf5d23..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/VoidParameterVoidReturn.swift +++ /dev/null @@ -1 +0,0 @@ -@JS func check() {} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/SnapshotTesting.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/SnapshotTesting.swift index ce7066a6d..de7ebd0c3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/SnapshotTesting.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/SnapshotTesting.swift @@ -22,17 +22,26 @@ func assertSnapshot( if FileManager.default.fileExists(atPath: snapshotPath.path) { let existingSnapshot = try String(contentsOf: snapshotPath, encoding: .utf8) - let ok = existingSnapshot == String(data: input, encoding: .utf8)! + let actual = String(data: input, encoding: .utf8)! + let ok = existingSnapshot == actual let actualFilePath = snapshotPath.path + ".actual" let updateSnapshots = ProcessInfo.processInfo.environment["UPDATE_SNAPSHOTS"] != nil - func buildComment() -> Comment { - "Snapshot mismatch: \(actualFilePath) \(snapshotPath.path)" - } + if !updateSnapshots { - #expect(ok, buildComment(), sourceLocation: sourceLocation) if !ok { - try input.write(to: URL(fileURLWithPath: actualFilePath)) + try actual.write(toFile: actualFilePath, atomically: true, encoding: .utf8) } + + let diff = ok ? nil : unifiedDiff(expectedPath: snapshotPath.path, actualPath: actualFilePath) + func buildComment() -> Comment { + var message = "Snapshot mismatch: \(actualFilePath) \(snapshotPath.path)" + if let diff { + message.append("\n\n" + diff) + } + return Comment(rawValue: message) + } + + #expect(ok, buildComment(), sourceLocation: sourceLocation) } else { try input.write(to: snapshotPath) } @@ -41,3 +50,23 @@ func assertSnapshot( #expect(Bool(false), "Snapshot created at \(snapshotPath.path)", sourceLocation: sourceLocation) } } + +private func unifiedDiff(expectedPath: String, actualPath: String) -> String? { + let process = Process() + process.executableURL = URL(fileURLWithPath: "/usr/bin/env") + process.arguments = ["diff", "-u", expectedPath, actualPath] + let output = Pipe() + process.standardOutput = output + process.standardError = Pipe() + + do { + try process.run() + } catch { + return nil + } + process.waitUntilExit() + + let data = output.fileHandleForReading.readDataToEndOfFile() + guard !data.isEmpty else { return nil } + return String(data: data, encoding: .utf8) +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/TS2SwiftVitestTests.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/TS2SwiftVitestTests.swift new file mode 100644 index 000000000..f658b001f --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/TS2SwiftVitestTests.swift @@ -0,0 +1,43 @@ +import Foundation +import Testing +@testable import TS2Swift + +/// Runs the TS2Swift JavaScript test suite (Vitest) so that `swift test --package-path ./Plugins/BridgeJS` +/// validates both the TypeScript ts2swift output and the Swift codegen. For fast iteration on ts2swift, +/// run `npm test` directly in `Sources/TS2Swift/JavaScript`. +@Suite struct TS2SwiftVitestTests { + @Test + func ts2SwiftVitestSuitePasses() throws { + let testFileURL = URL(fileURLWithPath: #filePath) + let ts2SwiftJSDir = + testFileURL + .deletingLastPathComponent() // BridgeJSToolTests + .deletingLastPathComponent() // Tests + .deletingLastPathComponent() // BridgeJS package root + .appendingPathComponent("Sources") + .appendingPathComponent("TS2Swift") + .appendingPathComponent("JavaScript") + let process = Process() + guard let npmExecutable = which("npm"), let nodeExecutable = which("node") else { + Issue.record("No \"npm\" command found in your system") + return + } + process.executableURL = npmExecutable + var environment = ProcessInfo.processInfo.environment + environment["PATH"] = + "\(nodeExecutable.deletingLastPathComponent().path)\(PATH_SEPARATOR) \(environment["PATH"] ?? "")" + process.environment = environment + var arguments = ["run", "test"] + if ProcessInfo.processInfo.environment["UPDATE_SNAPSHOTS"] != nil { + arguments.append(contentsOf: ["--", "--update"]) + } + process.arguments = arguments + process.currentDirectoryURL = ts2SwiftJSDir + try process.run() + process.waitUntilExit() + #expect( + process.terminationStatus == 0, + "TS2Swift Vitest suite failed (exit code \(process.terminationStatus)). Run `cd Sources/TS2Swift/JavaScript && npm test` for details." + ) + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/WhichTests.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/WhichTests.swift index 958d4d645..f82b3dfec 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/WhichTests.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/WhichTests.swift @@ -1,6 +1,6 @@ import Testing import Foundation -@testable import TS2Skeleton +@testable import TS2Swift @testable import BridgeJSCore @Suite struct WhichTests { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.json new file mode 100644 index 000000000..8eab0c059 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.json @@ -0,0 +1,1285 @@ +{ + "exported" : { + "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" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_processOptionalStringArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalStringArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_processOptionalArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_processOptionalPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalPointArray", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_processOptionalDirectionArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalDirectionArray", + "parameters" : [ + { + "label" : "_", + "name" : "directions", + "type" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_processOptionalStatusArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalStatusArray", + "parameters" : [ + { + "label" : "_", + "name" : "statuses", + "type" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Status", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Status", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + } + } + }, + { + "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" + } + } + } + } + } + } + }, + { + "abiName" : "bjs_processJSObjectArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processJSObjectArray", + "parameters" : [ + { + "label" : "_", + "name" : "objects", + "type" : { + "array" : { + "_0" : { + "jsObject" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "jsObject" : { + + } + } + } + } + }, + { + "abiName" : "bjs_processOptionalJSObjectArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalJSObjectArray", + "parameters" : [ + { + "label" : "_", + "name" : "objects", + "type" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "jsObject" : { + + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "jsObject" : { + + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_processNestedJSObjectArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processNestedJSObjectArray", + "parameters" : [ + { + "label" : "_", + "name" : "objects", + "type" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "jsObject" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "array" : { + "_0" : { + "jsObject" : { + + } + } + } + } + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + { + "methods" : [ + + ], + "name" : "Point", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "x", + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "y", + "type" : { + "double" : { + + } + } + } + ], + "swiftCallName" : "Point" + } + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "checkArray", + "parameters" : [ + { + "name" : "a", + "type" : { + "jsObject" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "checkArrayWithLength", + "parameters" : [ + { + "name" : "a", + "type" : { + "jsObject" : { + + } + } + }, + { + "name" : "b", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "importProcessNumbers", + "parameters" : [ + { + "name" : "values", + "type" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "importGetNumbers", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + }, + { + "name" : "importTransformNumbers", + "parameters" : [ + { + "name" : "values", + "type" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + }, + { + "name" : "importProcessStrings", + "parameters" : [ + { + "name" : "values", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "name" : "importProcessBooleans", + "parameters" : [ + { + "name" : "values", + "type" : { + "array" : { + "_0" : { + "bool" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "bool" : { + + } + } + } + } + } + ], + "types" : [ + + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift new file mode 100644 index 000000000..3141139ca --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift @@ -0,0 +1,616 @@ +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, _BridgedSwiftRawValueEnum { +} + +extension Point: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Point { + let y = Double.bridgeJSStackPop() + let x = Double.bridgeJSStackPop() + return Point(x: x, y: y) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.x.bridgeJSStackPush() + self.y.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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(_: [Int].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [String].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [Double].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [Bool].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [Point].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [Direction].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [Status].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [Int].bridgeJSStackPop()) + 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(_: [Point].bridgeJSStackPop(), 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(_: [UnsafeRawPointer].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [UnsafeMutableRawPointer].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [OpaquePointer].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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.bridgeJSStackPop()) + } + __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.bridgeJSStackPush() + } + _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.bridgeJSStackPop()) + } + __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.bridgeJSStackPush() + } + _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() -> Void { + #if arch(wasm32) + let ret = processOptionalArray(_: Optional<[Int]>.bridgeJSLiftParameter()) + ret.bridgeJSStackPush() + #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.bridgeJSStackPop()) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + __bjs_elem_ret.bridgeJSStackPush() + } + _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.bridgeJSStackPop()) + } + __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.bridgeJSStackPush() + } + _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.bridgeJSStackPop()) + } + __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.bridgeJSStackPush() + } + _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(_: [[Int]].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [[String]].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [[Point]].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [Item].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [[Item]].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processJSObjectArray") +@_cdecl("bjs_processJSObjectArray") +public func _bjs_processJSObjectArray() -> Void { + #if arch(wasm32) + let ret = processJSObjectArray(_: [JSObject].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processOptionalJSObjectArray") +@_cdecl("bjs_processOptionalJSObjectArray") +public func _bjs_processOptionalJSObjectArray() -> Void { + #if arch(wasm32) + let ret = processOptionalJSObjectArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0..<__count { + __result.append(Optional.bridgeJSStackPop()) + } + __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.bridgeJSStackPush() + } + _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_processNestedJSObjectArray") +@_cdecl("bjs_processNestedJSObjectArray") +public func _bjs_processNestedJSObjectArray() -> Void { + #if arch(wasm32) + let ret = processNestedJSObjectArray(_: [[JSObject]].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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 + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_checkArray") +fileprivate func bjs_checkArray(_ a: Int32) -> Void +#else +fileprivate func bjs_checkArray(_ a: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$checkArray(_ a: JSObject) throws(JSException) -> Void { + let aValue = a.bridgeJSLowerParameter() + bjs_checkArray(aValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_checkArrayWithLength") +fileprivate func bjs_checkArrayWithLength(_ a: Int32, _ b: Float64) -> Void +#else +fileprivate func bjs_checkArrayWithLength(_ a: Int32, _ b: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$checkArrayWithLength(_ a: JSObject, _ b: Double) throws(JSException) -> Void { + let aValue = a.bridgeJSLowerParameter() + let bValue = b.bridgeJSLowerParameter() + bjs_checkArrayWithLength(aValue, bValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_importProcessNumbers") +fileprivate func bjs_importProcessNumbers() -> Void +#else +fileprivate func bjs_importProcessNumbers() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$importProcessNumbers(_ values: [Double]) throws(JSException) -> Void { + let _ = values.bridgeJSLowerParameter() + bjs_importProcessNumbers() + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_importGetNumbers") +fileprivate func bjs_importGetNumbers() -> Void +#else +fileprivate func bjs_importGetNumbers() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$importGetNumbers() throws(JSException) -> [Double] { + bjs_importGetNumbers() + if let error = _swift_js_take_exception() { + throw error + } + return [Double].bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_importTransformNumbers") +fileprivate func bjs_importTransformNumbers() -> Void +#else +fileprivate func bjs_importTransformNumbers() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$importTransformNumbers(_ values: [Double]) throws(JSException) -> [Double] { + let _ = values.bridgeJSLowerParameter() + bjs_importTransformNumbers() + if let error = _swift_js_take_exception() { + throw error + } + return [Double].bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_importProcessStrings") +fileprivate func bjs_importProcessStrings() -> Void +#else +fileprivate func bjs_importProcessStrings() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$importProcessStrings(_ values: [String]) throws(JSException) -> [String] { + let _ = values.bridgeJSLowerParameter() + bjs_importProcessStrings() + if let error = _swift_js_take_exception() { + throw error + } + return [String].bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_importProcessBooleans") +fileprivate func bjs_importProcessBooleans() -> Void +#else +fileprivate func bjs_importProcessBooleans() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$importProcessBooleans(_ values: [Bool]) throws(JSException) -> [Bool] { + let _ = values.bridgeJSLowerParameter() + bjs_importProcessBooleans() + if let error = _swift_js_take_exception() { + throw error + } + return [Bool].bridgeJSLiftReturn() +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.json new file mode 100644 index 000000000..a780871ba --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.json @@ -0,0 +1,187 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_asyncReturnVoid", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncReturnVoid", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_asyncRoundTripInt", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripInt", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_asyncRoundTripString", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripString", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_asyncRoundTripBool", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripBool", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_asyncRoundTripFloat", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripFloat", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "float" : { + + } + } + } + ], + "returnType" : { + "float" : { + + } + } + }, + { + "abiName" : "bjs_asyncRoundTripDouble", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripDouble", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + { + "abiName" : "bjs_asyncRoundTripJSObject", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripJSObject", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "jsObject" : { + + } + } + } + ], + "returnType" : { + "jsObject" : { + + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.swift new file mode 100644 index 000000000..f5230f213 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.swift @@ -0,0 +1,90 @@ +@_expose(wasm, "bjs_asyncReturnVoid") +@_cdecl("bjs_asyncReturnVoid") +public func _bjs_asyncReturnVoid() -> Int32 { + #if arch(wasm32) + let ret = JSPromise.async { + await asyncReturnVoid() + }.jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripInt") +@_cdecl("bjs_asyncRoundTripInt") +public func _bjs_asyncRoundTripInt(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = JSPromise.async { + return await asyncRoundTripInt(_: Int.bridgeJSLiftParameter(v)).jsValue + }.jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripString") +@_cdecl("bjs_asyncRoundTripString") +public func _bjs_asyncRoundTripString(_ vBytes: Int32, _ vLength: Int32) -> Int32 { + #if arch(wasm32) + let ret = JSPromise.async { + return await asyncRoundTripString(_: String.bridgeJSLiftParameter(vBytes, vLength)).jsValue + }.jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripBool") +@_cdecl("bjs_asyncRoundTripBool") +public func _bjs_asyncRoundTripBool(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = JSPromise.async { + return await asyncRoundTripBool(_: Bool.bridgeJSLiftParameter(v)).jsValue + }.jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripFloat") +@_cdecl("bjs_asyncRoundTripFloat") +public func _bjs_asyncRoundTripFloat(_ v: Float32) -> Int32 { + #if arch(wasm32) + let ret = JSPromise.async { + return await asyncRoundTripFloat(_: Float.bridgeJSLiftParameter(v)).jsValue + }.jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripDouble") +@_cdecl("bjs_asyncRoundTripDouble") +public func _bjs_asyncRoundTripDouble(_ v: Float64) -> Int32 { + #if arch(wasm32) + let ret = JSPromise.async { + return await asyncRoundTripDouble(_: Double.bridgeJSLiftParameter(v)).jsValue + }.jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripJSObject") +@_cdecl("bjs_asyncRoundTripJSObject") +public func _bjs_asyncRoundTripJSObject(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = JSPromise.async { + return await asyncRoundTripJSObject(_: JSObject.bridgeJSLiftParameter(v)).jsValue + }.jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileFunctionTypes.ReverseOrder.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileFunctionTypes.ReverseOrder.json new file mode 100644 index 000000000..9b056b650 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileFunctionTypes.ReverseOrder.json @@ -0,0 +1,152 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_FunctionA_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_FunctionA_processB", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processB", + "parameters" : [ + { + "label" : "b", + "name" : "b", + "type" : { + "swiftHeapObject" : { + "_0" : "FunctionB" + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_FunctionA_createB", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createB", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "FunctionB" + } + } + } + ], + "name" : "FunctionA", + "properties" : [ + + ], + "swiftCallName" : "FunctionA" + }, + { + "constructor" : { + "abiName" : "bjs_FunctionB_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "string" : { + + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "FunctionB", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "FunctionB" + } + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_standaloneFunction", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "standaloneFunction", + "parameters" : [ + { + "label" : "b", + "name" : "b", + "type" : { + "swiftHeapObject" : { + "_0" : "FunctionB" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "FunctionB" + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileFunctionTypes.ReverseOrder.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileFunctionTypes.ReverseOrder.swift new file mode 100644 index 000000000..05437f540 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileFunctionTypes.ReverseOrder.swift @@ -0,0 +1,125 @@ +@_expose(wasm, "bjs_standaloneFunction") +@_cdecl("bjs_standaloneFunction") +public func _bjs_standaloneFunction(_ b: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = standaloneFunction(b: FunctionB.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_FunctionA_init") +@_cdecl("bjs_FunctionA_init") +public func _bjs_FunctionA_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = FunctionA() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_FunctionA_processB") +@_cdecl("bjs_FunctionA_processB") +public func _bjs_FunctionA_processB(_ _self: UnsafeMutableRawPointer, _ b: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = FunctionA.bridgeJSLiftParameter(_self).processB(b: FunctionB.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_FunctionA_createB") +@_cdecl("bjs_FunctionA_createB") +public func _bjs_FunctionA_createB(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = FunctionA.bridgeJSLiftParameter(_self).createB(value: String.bridgeJSLiftParameter(valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_FunctionA_deinit") +@_cdecl("bjs_FunctionA_deinit") +public func _bjs_FunctionA_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension FunctionA: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_FunctionA_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_FunctionA_wrap") +fileprivate func _bjs_FunctionA_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_FunctionA_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_FunctionB_init") +@_cdecl("bjs_FunctionB_init") +public func _bjs_FunctionB_init(_ valueBytes: Int32, _ valueLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = FunctionB(value: String.bridgeJSLiftParameter(valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_FunctionB_value_get") +@_cdecl("bjs_FunctionB_value_get") +public func _bjs_FunctionB_value_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = FunctionB.bridgeJSLiftParameter(_self).value + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_FunctionB_value_set") +@_cdecl("bjs_FunctionB_value_set") +public func _bjs_FunctionB_value_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + FunctionB.bridgeJSLiftParameter(_self).value = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_FunctionB_deinit") +@_cdecl("bjs_FunctionB_deinit") +public func _bjs_FunctionB_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension FunctionB: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_FunctionB_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_FunctionB_wrap") +fileprivate func _bjs_FunctionB_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_FunctionB_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileFunctionTypes.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileFunctionTypes.json new file mode 100644 index 000000000..d76a1622d --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileFunctionTypes.json @@ -0,0 +1,152 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_FunctionB_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "string" : { + + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "FunctionB", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "FunctionB" + }, + { + "constructor" : { + "abiName" : "bjs_FunctionA_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_FunctionA_processB", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processB", + "parameters" : [ + { + "label" : "b", + "name" : "b", + "type" : { + "swiftHeapObject" : { + "_0" : "FunctionB" + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_FunctionA_createB", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createB", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "FunctionB" + } + } + } + ], + "name" : "FunctionA", + "properties" : [ + + ], + "swiftCallName" : "FunctionA" + } + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_standaloneFunction", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "standaloneFunction", + "parameters" : [ + { + "label" : "b", + "name" : "b", + "type" : { + "swiftHeapObject" : { + "_0" : "FunctionB" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "FunctionB" + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileFunctionTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileFunctionTypes.swift new file mode 100644 index 000000000..fa8e80cd8 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileFunctionTypes.swift @@ -0,0 +1,125 @@ +@_expose(wasm, "bjs_standaloneFunction") +@_cdecl("bjs_standaloneFunction") +public func _bjs_standaloneFunction(_ b: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = standaloneFunction(b: FunctionB.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_FunctionB_init") +@_cdecl("bjs_FunctionB_init") +public func _bjs_FunctionB_init(_ valueBytes: Int32, _ valueLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = FunctionB(value: String.bridgeJSLiftParameter(valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_FunctionB_value_get") +@_cdecl("bjs_FunctionB_value_get") +public func _bjs_FunctionB_value_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = FunctionB.bridgeJSLiftParameter(_self).value + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_FunctionB_value_set") +@_cdecl("bjs_FunctionB_value_set") +public func _bjs_FunctionB_value_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + FunctionB.bridgeJSLiftParameter(_self).value = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_FunctionB_deinit") +@_cdecl("bjs_FunctionB_deinit") +public func _bjs_FunctionB_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension FunctionB: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_FunctionB_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_FunctionB_wrap") +fileprivate func _bjs_FunctionB_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_FunctionB_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_FunctionA_init") +@_cdecl("bjs_FunctionA_init") +public func _bjs_FunctionA_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = FunctionA() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_FunctionA_processB") +@_cdecl("bjs_FunctionA_processB") +public func _bjs_FunctionA_processB(_ _self: UnsafeMutableRawPointer, _ b: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = FunctionA.bridgeJSLiftParameter(_self).processB(b: FunctionB.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_FunctionA_createB") +@_cdecl("bjs_FunctionA_createB") +public func _bjs_FunctionA_createB(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = FunctionA.bridgeJSLiftParameter(_self).createB(value: String.bridgeJSLiftParameter(valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_FunctionA_deinit") +@_cdecl("bjs_FunctionA_deinit") +public func _bjs_FunctionA_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension FunctionA: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_FunctionA_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_FunctionA_wrap") +fileprivate func _bjs_FunctionA_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_FunctionA_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileSkipsEmptySkeletons.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileSkipsEmptySkeletons.json new file mode 100644 index 000000000..10c079b27 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileSkipsEmptySkeletons.json @@ -0,0 +1,25 @@ +{ + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "fetchNumber", + "parameters" : [ + + ], + "returnType" : { + "int" : { + + } + } + } + ], + "types" : [ + + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileSkipsEmptySkeletons.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileSkipsEmptySkeletons.swift new file mode 100644 index 000000000..21e4e939a --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileSkipsEmptySkeletons.swift @@ -0,0 +1,16 @@ +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_fetchNumber") +fileprivate func bjs_fetchNumber() -> Int32 +#else +fileprivate func bjs_fetchNumber() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$fetchNumber() throws(JSException) -> Int { + let ret = bjs_fetchNumber() + if let error = _swift_js_take_exception() { + throw error + } + return Int.bridgeJSLiftReturn(ret) +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.ReverseOrder.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.ReverseOrder.json new file mode 100644 index 000000000..59fb8484a --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.ReverseOrder.json @@ -0,0 +1,65 @@ +{ + "exported" : { + "classes" : [ + { + "methods" : [ + + ], + "name" : "ClassA", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "linkedB", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "ClassB" + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "ClassA" + }, + { + "constructor" : { + "abiName" : "bjs_ClassB_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + + ], + "name" : "ClassB", + "properties" : [ + + ], + "swiftCallName" : "ClassB" + } + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.ReverseOrder.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.ReverseOrder.swift new file mode 100644 index 000000000..8d697f8ba --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.ReverseOrder.swift @@ -0,0 +1,81 @@ +@_expose(wasm, "bjs_ClassA_linkedB_get") +@_cdecl("bjs_ClassA_linkedB_get") +public func _bjs_ClassA_linkedB_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ClassA.bridgeJSLiftParameter(_self).linkedB + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClassA_linkedB_set") +@_cdecl("bjs_ClassA_linkedB_set") +public func _bjs_ClassA_linkedB_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + ClassA.bridgeJSLiftParameter(_self).linkedB = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClassA_deinit") +@_cdecl("bjs_ClassA_deinit") +public func _bjs_ClassA_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension ClassA: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_ClassA_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_ClassA_wrap") +fileprivate func _bjs_ClassA_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_ClassA_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_ClassB_init") +@_cdecl("bjs_ClassB_init") +public func _bjs_ClassB_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = ClassB() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClassB_deinit") +@_cdecl("bjs_ClassB_deinit") +public func _bjs_ClassB_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension ClassB: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_ClassB_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_ClassB_wrap") +fileprivate func _bjs_ClassB_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_ClassB_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.json new file mode 100644 index 000000000..cc10331a4 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.json @@ -0,0 +1,65 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_ClassB_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + + ], + "name" : "ClassB", + "properties" : [ + + ], + "swiftCallName" : "ClassB" + }, + { + "methods" : [ + + ], + "name" : "ClassA", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "linkedB", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "ClassB" + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "ClassA" + } + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.swift new file mode 100644 index 000000000..0a0396075 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.swift @@ -0,0 +1,81 @@ +@_expose(wasm, "bjs_ClassB_init") +@_cdecl("bjs_ClassB_init") +public func _bjs_ClassB_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = ClassB() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClassB_deinit") +@_cdecl("bjs_ClassB_deinit") +public func _bjs_ClassB_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension ClassB: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_ClassB_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_ClassB_wrap") +fileprivate func _bjs_ClassB_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_ClassB_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_ClassA_linkedB_get") +@_cdecl("bjs_ClassA_linkedB_get") +public func _bjs_ClassA_linkedB_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ClassA.bridgeJSLiftParameter(_self).linkedB + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClassA_linkedB_set") +@_cdecl("bjs_ClassA_linkedB_set") +public func _bjs_ClassA_linkedB_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + ClassA.bridgeJSLiftParameter(_self).linkedB = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClassA_deinit") +@_cdecl("bjs_ClassA_deinit") +public func _bjs_ClassA_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension ClassA: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_ClassA_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_ClassA_wrap") +fileprivate func _bjs_ClassA_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_ClassA_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.json new file mode 100644 index 000000000..8c088a35e --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.json @@ -0,0 +1,1283 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_DefaultGreeter_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "DefaultGreeter", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "DefaultGreeter" + }, + { + "constructor" : { + "abiName" : "bjs_EmptyGreeter_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + + ], + "name" : "EmptyGreeter", + "properties" : [ + + ], + "swiftCallName" : "EmptyGreeter" + }, + { + "constructor" : { + "abiName" : "bjs_ConstructorDefaults_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "defaultValue" : { + "string" : { + "_0" : "Default" + } + }, + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "defaultValue" : { + "int" : { + "_0" : 42 + } + }, + "label" : "count", + "name" : "count", + "type" : { + "int" : { + + } + } + }, + { + "defaultValue" : { + "bool" : { + "_0" : true + } + }, + "label" : "enabled", + "name" : "enabled", + "type" : { + "bool" : { + + } + } + }, + { + "defaultValue" : { + "enumCase" : { + "_0" : "Status", + "_1" : "active" + } + }, + "label" : "status", + "name" : "status", + "type" : { + "caseEnum" : { + "_0" : "Status" + } + } + }, + { + "defaultValue" : { + "null" : { + + } + }, + "label" : "tag", + "name" : "tag", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "ConstructorDefaults", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "count", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "enabled", + "type" : { + "bool" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "status", + "type" : { + "caseEnum" : { + "_0" : "Status" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "tag", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "ConstructorDefaults" + } + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "active" + }, + { + "associatedValues" : [ + + ], + "name" : "inactive" + }, + { + "associatedValues" : [ + + ], + "name" : "pending" + } + ], + "emitStyle" : "const", + "explicitAccessControl" : "public", + "name" : "Status", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Status", + "tsFullPath" : "Status" + } + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_testStringDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testStringDefault", + "parameters" : [ + { + "defaultValue" : { + "string" : { + "_0" : "Hello World" + } + }, + "label" : "message", + "name" : "message", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_testNegativeIntDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testNegativeIntDefault", + "parameters" : [ + { + "defaultValue" : { + "int" : { + "_0" : -42 + } + }, + "label" : "value", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_testBoolDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testBoolDefault", + "parameters" : [ + { + "defaultValue" : { + "bool" : { + "_0" : true + } + }, + "label" : "flag", + "name" : "flag", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_testNegativeFloatDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testNegativeFloatDefault", + "parameters" : [ + { + "defaultValue" : { + "float" : { + "_0" : -273.15 + } + }, + "label" : "temp", + "name" : "temp", + "type" : { + "float" : { + + } + } + } + ], + "returnType" : { + "float" : { + + } + } + }, + { + "abiName" : "bjs_testDoubleDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testDoubleDefault", + "parameters" : [ + { + "defaultValue" : { + "double" : { + "_0" : 2.718 + } + }, + "label" : "precision", + "name" : "precision", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + { + "abiName" : "bjs_testOptionalDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testOptionalDefault", + "parameters" : [ + { + "defaultValue" : { + "null" : { + + } + }, + "label" : "name", + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_testOptionalStringDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testOptionalStringDefault", + "parameters" : [ + { + "defaultValue" : { + "string" : { + "_0" : "Hi" + } + }, + "label" : "greeting", + "name" : "greeting", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_testMultipleDefaults", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testMultipleDefaults", + "parameters" : [ + { + "defaultValue" : { + "string" : { + "_0" : "Default Title" + } + }, + "label" : "title", + "name" : "title", + "type" : { + "string" : { + + } + } + }, + { + "defaultValue" : { + "int" : { + "_0" : 10 + } + }, + "label" : "count", + "name" : "count", + "type" : { + "int" : { + + } + } + }, + { + "defaultValue" : { + "bool" : { + "_0" : false + } + }, + "label" : "enabled", + "name" : "enabled", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_testEnumDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testEnumDefault", + "parameters" : [ + { + "defaultValue" : { + "enumCase" : { + "_0" : "Status", + "_1" : "active" + } + }, + "label" : "status", + "name" : "status", + "type" : { + "caseEnum" : { + "_0" : "Status" + } + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "Status" + } + } + }, + { + "abiName" : "bjs_testComplexInit", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testComplexInit", + "parameters" : [ + { + "defaultValue" : { + "objectWithArguments" : { + "_0" : "DefaultGreeter", + "_1" : [ + { + "string" : { + "_0" : "DefaultUser" + } + } + ] + } + }, + "label" : "greeter", + "name" : "greeter", + "type" : { + "swiftHeapObject" : { + "_0" : "DefaultGreeter" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "DefaultGreeter" + } + } + }, + { + "abiName" : "bjs_testEmptyInit", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testEmptyInit", + "parameters" : [ + { + "defaultValue" : { + "object" : { + "_0" : "EmptyGreeter" + } + }, + "label" : "greeter", + "name" : "greeter", + "type" : { + "swiftHeapObject" : { + "_0" : "EmptyGreeter" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "EmptyGreeter" + } + } + }, + { + "abiName" : "bjs_testOptionalStructDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testOptionalStructDefault", + "parameters" : [ + { + "defaultValue" : { + "null" : { + + } + }, + "label" : "point", + "name" : "point", + "type" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Config" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Config" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_testOptionalStructWithValueDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testOptionalStructWithValueDefault", + "parameters" : [ + { + "defaultValue" : { + "structLiteral" : { + "_0" : "Config", + "_1" : [ + { + "name" : "name", + "value" : { + "string" : { + "_0" : "default" + } + } + }, + { + "name" : "value", + "value" : { + "int" : { + "_0" : 42 + } + } + }, + { + "name" : "enabled", + "value" : { + "bool" : { + "_0" : true + } + } + } + ] + } + }, + "label" : "point", + "name" : "point", + "type" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Config" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Config" + } + }, + "_1" : "null" + } + } + }, + { + "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" : [ + + ], + "structs" : [ + { + "methods" : [ + + ], + "name" : "Config", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "value", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "enabled", + "type" : { + "bool" : { + + } + } + } + ], + "swiftCallName" : "Config" + }, + { + "constructor" : { + "abiName" : "bjs_MathOperations_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "defaultValue" : { + "double" : { + "_0" : 0 + } + }, + "label" : "baseValue", + "name" : "baseValue", + "type" : { + "double" : { + + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_MathOperations_add", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "add", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "double" : { + + } + } + }, + { + "defaultValue" : { + "double" : { + "_0" : 10 + } + }, + "label" : "b", + "name" : "b", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + { + "abiName" : "bjs_MathOperations_multiply", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "multiply", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "double" : { + + } + } + }, + { + "label" : "b", + "name" : "b", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + { + "abiName" : "bjs_MathOperations_static_subtract", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "subtract", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "double" : { + + } + } + }, + { + "defaultValue" : { + "double" : { + "_0" : 5 + } + }, + "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" + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.swift new file mode 100644 index 000000000..e8f367f1c --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.swift @@ -0,0 +1,615 @@ +extension Status: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Status { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Status { + return Status(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .active + case 1: + self = .inactive + case 2: + self = .pending + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .active: + return 0 + case .inactive: + return 1 + case .pending: + return 2 + } + } +} + +extension Config: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Config { + let enabled = Bool.bridgeJSStackPop() + let value = Int.bridgeJSStackPop() + let name = String.bridgeJSStackPop() + return Config(name: name, value: value, enabled: enabled) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.name.bridgeJSStackPush() + self.value.bridgeJSStackPush() + self.enabled.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Config(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> MathOperations { + let baseValue = Double.bridgeJSStackPop() + return MathOperations(baseValue: baseValue) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.baseValue.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_MathOperations(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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") +public func _bjs_MathOperations_init(_ baseValue: Float64) -> Void { + #if arch(wasm32) + let ret = MathOperations(baseValue: Double.bridgeJSLiftParameter(baseValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathOperations_add") +@_cdecl("bjs_MathOperations_add") +public func _bjs_MathOperations_add(_ a: Float64, _ b: Float64) -> Float64 { + #if arch(wasm32) + let ret = MathOperations.bridgeJSLiftParameter().add(a: Double.bridgeJSLiftParameter(a), b: Double.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathOperations_multiply") +@_cdecl("bjs_MathOperations_multiply") +public func _bjs_MathOperations_multiply(_ a: Float64, _ b: Float64) -> Float64 { + #if arch(wasm32) + let ret = MathOperations.bridgeJSLiftParameter().multiply(a: Double.bridgeJSLiftParameter(a), b: Double.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathOperations_static_subtract") +@_cdecl("bjs_MathOperations_static_subtract") +public func _bjs_MathOperations_static_subtract(_ a: Float64, _ b: Float64) -> Float64 { + #if arch(wasm32) + let ret = MathOperations.subtract(a: Double.bridgeJSLiftParameter(a), b: Double.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testStringDefault") +@_cdecl("bjs_testStringDefault") +public func _bjs_testStringDefault(_ messageBytes: Int32, _ messageLength: Int32) -> Void { + #if arch(wasm32) + let ret = testStringDefault(message: String.bridgeJSLiftParameter(messageBytes, messageLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testNegativeIntDefault") +@_cdecl("bjs_testNegativeIntDefault") +public func _bjs_testNegativeIntDefault(_ value: Int32) -> Int32 { + #if arch(wasm32) + let ret = testNegativeIntDefault(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testBoolDefault") +@_cdecl("bjs_testBoolDefault") +public func _bjs_testBoolDefault(_ flag: Int32) -> Int32 { + #if arch(wasm32) + let ret = testBoolDefault(flag: Bool.bridgeJSLiftParameter(flag)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testNegativeFloatDefault") +@_cdecl("bjs_testNegativeFloatDefault") +public func _bjs_testNegativeFloatDefault(_ temp: Float32) -> Float32 { + #if arch(wasm32) + let ret = testNegativeFloatDefault(temp: Float.bridgeJSLiftParameter(temp)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testDoubleDefault") +@_cdecl("bjs_testDoubleDefault") +public func _bjs_testDoubleDefault(_ precision: Float64) -> Float64 { + #if arch(wasm32) + let ret = testDoubleDefault(precision: Double.bridgeJSLiftParameter(precision)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testOptionalDefault") +@_cdecl("bjs_testOptionalDefault") +public func _bjs_testOptionalDefault(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = testOptionalDefault(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testOptionalStringDefault") +@_cdecl("bjs_testOptionalStringDefault") +public func _bjs_testOptionalStringDefault(_ greetingIsSome: Int32, _ greetingBytes: Int32, _ greetingLength: Int32) -> Void { + #if arch(wasm32) + let ret = testOptionalStringDefault(greeting: Optional.bridgeJSLiftParameter(greetingIsSome, greetingBytes, greetingLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testMultipleDefaults") +@_cdecl("bjs_testMultipleDefaults") +public func _bjs_testMultipleDefaults(_ titleBytes: Int32, _ titleLength: Int32, _ count: Int32, _ enabled: Int32) -> Void { + #if arch(wasm32) + let ret = testMultipleDefaults(title: String.bridgeJSLiftParameter(titleBytes, titleLength), count: Int.bridgeJSLiftParameter(count), enabled: Bool.bridgeJSLiftParameter(enabled)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testEnumDefault") +@_cdecl("bjs_testEnumDefault") +public func _bjs_testEnumDefault(_ status: Int32) -> Int32 { + #if arch(wasm32) + let ret = testEnumDefault(status: Status.bridgeJSLiftParameter(status)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testComplexInit") +@_cdecl("bjs_testComplexInit") +public func _bjs_testComplexInit(_ greeter: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = testComplexInit(greeter: DefaultGreeter.bridgeJSLiftParameter(greeter)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testEmptyInit") +@_cdecl("bjs_testEmptyInit") +public func _bjs_testEmptyInit(_ greeter: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = testEmptyInit(greeter: EmptyGreeter.bridgeJSLiftParameter(greeter)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testOptionalStructDefault") +@_cdecl("bjs_testOptionalStructDefault") +public func _bjs_testOptionalStructDefault() -> Void { + #if arch(wasm32) + let ret = testOptionalStructDefault(point: Optional.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testOptionalStructWithValueDefault") +@_cdecl("bjs_testOptionalStructWithValueDefault") +public func _bjs_testOptionalStructWithValueDefault() -> Void { + #if arch(wasm32) + let ret = testOptionalStructWithValueDefault(point: Optional.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testIntArrayDefault") +@_cdecl("bjs_testIntArrayDefault") +public func _bjs_testIntArrayDefault() -> Void { + #if arch(wasm32) + let ret = testIntArrayDefault(values: [Int].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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: [String].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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: [Double].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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: [Bool].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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: [Int].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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: [Int].bridgeJSStackPop(), 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 { + #if arch(wasm32) + let ret = DefaultGreeter(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DefaultGreeter_name_get") +@_cdecl("bjs_DefaultGreeter_name_get") +public func _bjs_DefaultGreeter_name_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = DefaultGreeter.bridgeJSLiftParameter(_self).name + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DefaultGreeter_name_set") +@_cdecl("bjs_DefaultGreeter_name_set") +public func _bjs_DefaultGreeter_name_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + DefaultGreeter.bridgeJSLiftParameter(_self).name = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DefaultGreeter_deinit") +@_cdecl("bjs_DefaultGreeter_deinit") +public func _bjs_DefaultGreeter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension DefaultGreeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_DefaultGreeter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_DefaultGreeter_wrap") +fileprivate func _bjs_DefaultGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_DefaultGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_EmptyGreeter_init") +@_cdecl("bjs_EmptyGreeter_init") +public func _bjs_EmptyGreeter_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = EmptyGreeter() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EmptyGreeter_deinit") +@_cdecl("bjs_EmptyGreeter_deinit") +public func _bjs_EmptyGreeter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension EmptyGreeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_EmptyGreeter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_EmptyGreeter_wrap") +fileprivate func _bjs_EmptyGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_EmptyGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_ConstructorDefaults_init") +@_cdecl("bjs_ConstructorDefaults_init") +public func _bjs_ConstructorDefaults_init(_ nameBytes: Int32, _ nameLength: Int32, _ count: Int32, _ enabled: Int32, _ status: Int32, _ tagIsSome: Int32, _ tagBytes: Int32, _ tagLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = ConstructorDefaults(name: String.bridgeJSLiftParameter(nameBytes, nameLength), count: Int.bridgeJSLiftParameter(count), enabled: Bool.bridgeJSLiftParameter(enabled), status: Status.bridgeJSLiftParameter(status), tag: Optional.bridgeJSLiftParameter(tagIsSome, tagBytes, tagLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_name_get") +@_cdecl("bjs_ConstructorDefaults_name_get") +public func _bjs_ConstructorDefaults_name_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ConstructorDefaults.bridgeJSLiftParameter(_self).name + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_name_set") +@_cdecl("bjs_ConstructorDefaults_name_set") +public func _bjs_ConstructorDefaults_name_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + ConstructorDefaults.bridgeJSLiftParameter(_self).name = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_count_get") +@_cdecl("bjs_ConstructorDefaults_count_get") +public func _bjs_ConstructorDefaults_count_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = ConstructorDefaults.bridgeJSLiftParameter(_self).count + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_count_set") +@_cdecl("bjs_ConstructorDefaults_count_set") +public func _bjs_ConstructorDefaults_count_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + ConstructorDefaults.bridgeJSLiftParameter(_self).count = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_enabled_get") +@_cdecl("bjs_ConstructorDefaults_enabled_get") +public func _bjs_ConstructorDefaults_enabled_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = ConstructorDefaults.bridgeJSLiftParameter(_self).enabled + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_enabled_set") +@_cdecl("bjs_ConstructorDefaults_enabled_set") +public func _bjs_ConstructorDefaults_enabled_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + ConstructorDefaults.bridgeJSLiftParameter(_self).enabled = Bool.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_status_get") +@_cdecl("bjs_ConstructorDefaults_status_get") +public func _bjs_ConstructorDefaults_status_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = ConstructorDefaults.bridgeJSLiftParameter(_self).status + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_status_set") +@_cdecl("bjs_ConstructorDefaults_status_set") +public func _bjs_ConstructorDefaults_status_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + ConstructorDefaults.bridgeJSLiftParameter(_self).status = Status.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_tag_get") +@_cdecl("bjs_ConstructorDefaults_tag_get") +public func _bjs_ConstructorDefaults_tag_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ConstructorDefaults.bridgeJSLiftParameter(_self).tag + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_tag_set") +@_cdecl("bjs_ConstructorDefaults_tag_set") +public func _bjs_ConstructorDefaults_tag_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + ConstructorDefaults.bridgeJSLiftParameter(_self).tag = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_deinit") +@_cdecl("bjs_ConstructorDefaults_deinit") +public func _bjs_ConstructorDefaults_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension ConstructorDefaults: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_ConstructorDefaults_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_ConstructorDefaults_wrap") +fileprivate func _bjs_ConstructorDefaults_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_ConstructorDefaults_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DictionaryTypes.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DictionaryTypes.json new file mode 100644 index 000000000..af5b83dc7 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DictionaryTypes.json @@ -0,0 +1,259 @@ +{ + "exported" : { + "classes" : [ + { + "methods" : [ + + ], + "name" : "Box", + "properties" : [ + + ], + "swiftCallName" : "Box" + } + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_mirrorDictionary", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "mirrorDictionary", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "dictionary" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "abiName" : "bjs_optionalDictionary", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "optionalDictionary", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "nullable" : { + "_0" : { + "dictionary" : { + "_0" : { + "string" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "dictionary" : { + "_0" : { + "string" : { + + } + } + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_nestedDictionary", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "nestedDictionary", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "dictionary" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + } + }, + { + "abiName" : "bjs_boxDictionary", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "boxDictionary", + "parameters" : [ + { + "label" : "_", + "name" : "boxes", + "type" : { + "dictionary" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Box" + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Box" + } + } + } + } + }, + { + "abiName" : "bjs_optionalBoxDictionary", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "optionalBoxDictionary", + "parameters" : [ + { + "label" : "_", + "name" : "boxes", + "type" : { + "dictionary" : { + "_0" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Box" + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Box" + } + }, + "_1" : "null" + } + } + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "importMirrorDictionary", + "parameters" : [ + { + "name" : "values", + "type" : { + "dictionary" : { + "_0" : { + "double" : { + + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "double" : { + + } + } + } + } + } + ], + "types" : [ + + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DictionaryTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DictionaryTypes.swift new file mode 100644 index 000000000..016a5f814 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DictionaryTypes.swift @@ -0,0 +1,97 @@ +@_expose(wasm, "bjs_mirrorDictionary") +@_cdecl("bjs_mirrorDictionary") +public func _bjs_mirrorDictionary() -> Void { + #if arch(wasm32) + let ret = mirrorDictionary(_: [String: Int].bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_optionalDictionary") +@_cdecl("bjs_optionalDictionary") +public func _bjs_optionalDictionary() -> Void { + #if arch(wasm32) + let ret = optionalDictionary(_: Optional<[String: String]>.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_nestedDictionary") +@_cdecl("bjs_nestedDictionary") +public func _bjs_nestedDictionary() -> Void { + #if arch(wasm32) + let ret = nestedDictionary(_: [String: [Int]].bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_boxDictionary") +@_cdecl("bjs_boxDictionary") +public func _bjs_boxDictionary() -> Void { + #if arch(wasm32) + let ret = boxDictionary(_: [String: Box].bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_optionalBoxDictionary") +@_cdecl("bjs_optionalBoxDictionary") +public func _bjs_optionalBoxDictionary() -> Void { + #if arch(wasm32) + let ret = optionalBoxDictionary(_: [String: Optional].bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Box_deinit") +@_cdecl("bjs_Box_deinit") +public func _bjs_Box_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Box: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Box_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Box_wrap") +fileprivate func _bjs_Box_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Box_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_importMirrorDictionary") +fileprivate func bjs_importMirrorDictionary() -> Void +#else +fileprivate func bjs_importMirrorDictionary() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$importMirrorDictionary(_ values: [String: Double]) throws(JSException) -> [String: Double] { + let _ = values.bridgeJSLowerParameter() + bjs_importMirrorDictionary() + if let error = _swift_js_take_exception() { + throw error + } + return [String: Double].bridgeJSLiftReturn() +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.json new file mode 100644 index 000000000..3c624fa12 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.json @@ -0,0 +1,1423 @@ +{ + "exported" : { + "classes" : [ + { + "methods" : [ + + ], + "name" : "User", + "properties" : [ + + ], + "swiftCallName" : "User" + } + ], + "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" : [ + + ], + "name" : "info" + } + ], + "emitStyle" : "const", + "name" : "APIResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "APIResult", + "tsFullPath" : "APIResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "error" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "status" + }, + { + "associatedValues" : [ + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + } + ], + "name" : "coordinates" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "comprehensive" + }, + { + "associatedValues" : [ + + ], + "name" : "info" + } + ], + "emitStyle" : "const", + "name" : "ComplexResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "ComplexResult", + "tsFullPath" : "ComplexResult" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Utilities", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utilities", + "tsFullPath" : "Utilities" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "status" + } + ], + "emitStyle" : "const", + "name" : "Result", + "namespace" : [ + "Utilities" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utilities.Result", + "tsFullPath" : "Utilities.Result" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + } + ], + "emitStyle" : "const", + "name" : "NetworkingResult", + "namespace" : [ + "API" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "NetworkingResult", + "tsFullPath" : "API.NetworkingResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + }, + { + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "name" : "status" + } + ], + "emitStyle" : "const", + "name" : "APIOptionalResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "APIOptionalResult", + "tsFullPath" : "APIOptionalResult" + }, + { + "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" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "north" + }, + { + "associatedValues" : [ + + ], + "name" : "south" + }, + { + "associatedValues" : [ + + ], + "name" : "east" + }, + { + "associatedValues" : [ + + ], + "name" : "west" + } + ], + "emitStyle" : "const", + "name" : "CardinalDirection", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "CardinalDirection", + "tsFullPath" : "CardinalDirection" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" + } + } + } + ], + "name" : "precision" + }, + { + "associatedValues" : [ + { + "type" : { + "caseEnum" : { + "_0" : "CardinalDirection" + } + } + } + ], + "name" : "direction" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" + } + }, + "_1" : "null" + } + } + } + ], + "name" : "optPrecision" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "CardinalDirection" + } + }, + "_1" : "null" + } + } + } + ], + "name" : "optDirection" + }, + { + "associatedValues" : [ + + ], + "name" : "empty" + } + ], + "emitStyle" : "const", + "name" : "TypedPayloadResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "TypedPayloadResult", + "tsFullPath" : "TypedPayloadResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + ], + "name" : "structPayload" + }, + { + "associatedValues" : [ + { + "type" : { + "swiftHeapObject" : { + "_0" : "User" + } + } + } + ], + "name" : "classPayload" + }, + { + "associatedValues" : [ + { + "type" : { + "jsObject" : { + + } + } + } + ], + "name" : "jsObjectPayload" + }, + { + "associatedValues" : [ + { + "type" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + ], + "name" : "nestedEnum" + }, + { + "associatedValues" : [ + { + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "name" : "arrayPayload" + }, + { + "associatedValues" : [ + + ], + "name" : "empty" + } + ], + "emitStyle" : "const", + "name" : "AllTypesResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "AllTypesResult", + "tsFullPath" : "AllTypesResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + }, + "_1" : "null" + } + } + } + ], + "name" : "optStruct" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "User" + } + }, + "_1" : "null" + } + } + } + ], + "name" : "optClass" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "jsObject" : { + + } + }, + "_1" : "null" + } + } + } + ], + "name" : "optJSObject" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + } + ], + "name" : "optNestedEnum" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "name" : "optArray" + }, + { + "associatedValues" : [ + + ], + "name" : "empty" + } + ], + "emitStyle" : "const", + "name" : "OptionalAllTypesResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "OptionalAllTypesResult", + "tsFullPath" : "OptionalAllTypesResult" + } + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_handle", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "handle", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getResult", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_roundtripAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripAPIResult", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalAPIResult", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_handleComplex", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "handleComplex", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getComplexResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getComplexResult", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_roundtripComplexResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripComplexResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalComplexResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalComplexResult", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalUtilitiesResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalUtilitiesResult", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "Utilities.Result" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "Utilities.Result" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalNetworkingResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalNetworkingResult", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "NetworkingResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "NetworkingResult" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalAPIOptionalResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalAPIOptionalResult", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIOptionalResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIOptionalResult" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_compareAPIResults", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "compareAPIResults", + "parameters" : [ + { + "label" : "result1", + "name" : "result1", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIOptionalResult" + } + }, + "_1" : "null" + } + } + }, + { + "label" : "result2", + "name" : "result2", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIOptionalResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIOptionalResult" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripTypedPayloadResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripTypedPayloadResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "TypedPayloadResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "TypedPayloadResult" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalTypedPayloadResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTypedPayloadResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "TypedPayloadResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "TypedPayloadResult" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripAllTypesResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripAllTypesResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "AllTypesResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "AllTypesResult" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalAllTypesResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalAllTypesResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "AllTypesResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "AllTypesResult" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalPayloadResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalPayloadResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "OptionalAllTypesResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "OptionalAllTypesResult" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalPayloadResultOpt", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalPayloadResultOpt", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "OptionalAllTypesResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "OptionalAllTypesResult" + } + }, + "_1" : "null" + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + { + "methods" : [ + + ], + "name" : "Point", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "x", + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "y", + "type" : { + "double" : { + + } + } + } + ], + "swiftCallName" : "Point" + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift new file mode 100644 index 000000000..3d23c6bff --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift @@ -0,0 +1,669 @@ +extension APIResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> APIResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(Int.bridgeJSStackPop()) + case 2: + return .flag(Bool.bridgeJSStackPop()) + case 3: + return .rate(Float.bridgeJSStackPop()) + case 4: + return .precise(Double.bridgeJSStackPop()) + case 5: + return .info + default: + fatalError("Unknown APIResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .failure(let param0): + param0.bridgeJSStackPush() + return Int32(1) + case .flag(let param0): + param0.bridgeJSStackPush() + return Int32(2) + case .rate(let param0): + param0.bridgeJSStackPush() + return Int32(3) + case .precise(let param0): + param0.bridgeJSStackPush() + return Int32(4) + case .info: + return Int32(5) + } + } +} + +extension ComplexResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> ComplexResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .error(String.bridgeJSStackPop(), Int.bridgeJSStackPop()) + case 2: + return .status(Bool.bridgeJSStackPop(), Int.bridgeJSStackPop(), String.bridgeJSStackPop()) + case 3: + return .coordinates(Double.bridgeJSStackPop(), Double.bridgeJSStackPop(), Double.bridgeJSStackPop()) + case 4: + return .comprehensive(Bool.bridgeJSStackPop(), Bool.bridgeJSStackPop(), Int.bridgeJSStackPop(), Int.bridgeJSStackPop(), Double.bridgeJSStackPop(), Double.bridgeJSStackPop(), String.bridgeJSStackPop(), String.bridgeJSStackPop(), String.bridgeJSStackPop()) + case 5: + return .info + default: + fatalError("Unknown ComplexResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .error(let param0, let param1): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + return Int32(1) + case .status(let param0, let param1, let param2): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + param2.bridgeJSStackPush() + return Int32(2) + case .coordinates(let param0, let param1, let param2): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + param2.bridgeJSStackPush() + return Int32(3) + case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + param2.bridgeJSStackPush() + param3.bridgeJSStackPush() + param4.bridgeJSStackPush() + param5.bridgeJSStackPush() + param6.bridgeJSStackPush() + param7.bridgeJSStackPush() + param8.bridgeJSStackPush() + return Int32(4) + case .info: + return Int32(5) + } + } +} + +extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> Utilities.Result { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(String.bridgeJSStackPop(), Int.bridgeJSStackPop()) + case 2: + return .status(Bool.bridgeJSStackPop(), Int.bridgeJSStackPop(), String.bridgeJSStackPop()) + default: + fatalError("Unknown Utilities.Result case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .failure(let param0, let param1): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + return Int32(1) + case .status(let param0, let param1, let param2): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + param2.bridgeJSStackPush() + return Int32(2) + } + } +} + +extension NetworkingResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> NetworkingResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(String.bridgeJSStackPop(), Int.bridgeJSStackPop()) + default: + fatalError("Unknown NetworkingResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .failure(let param0, let param1): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + return Int32(1) + } + } +} + +extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> APIOptionalResult { + switch caseId { + case 0: + return .success(Optional.bridgeJSStackPop()) + case 1: + return .failure(Optional.bridgeJSStackPop(), Optional.bridgeJSStackPop()) + case 2: + return .status(Optional.bridgeJSStackPop(), Optional.bridgeJSStackPop(), Optional.bridgeJSStackPop()) + default: + fatalError("Unknown APIOptionalResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + return Int32(0) + case .failure(let param0, let param1): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + let __bjs_isSome_param1 = param1 != nil + if let __bjs_unwrapped_param1 = param1 { + __bjs_unwrapped_param1.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) + return Int32(1) + case .status(let param0, let param1, let param2): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + let __bjs_isSome_param1 = param1 != nil + if let __bjs_unwrapped_param1 = param1 { + __bjs_unwrapped_param1.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) + let __bjs_isSome_param2 = param2 != nil + if let __bjs_unwrapped_param2 = param2 { + __bjs_unwrapped_param2.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param2 ? 1 : 0) + return Int32(2) + } + } +} + +extension Precision: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension CardinalDirection: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> CardinalDirection { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> CardinalDirection { + return CardinalDirection(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 TypedPayloadResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> TypedPayloadResult { + switch caseId { + case 0: + return .precision(Precision.bridgeJSStackPop()) + case 1: + return .direction(CardinalDirection.bridgeJSStackPop()) + case 2: + return .optPrecision(Optional.bridgeJSStackPop()) + case 3: + return .optDirection(Optional.bridgeJSStackPop()) + case 4: + return .empty + default: + fatalError("Unknown TypedPayloadResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .precision(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .direction(let param0): + param0.bridgeJSStackPush() + return Int32(1) + case .optPrecision(let param0): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + return Int32(2) + case .optDirection(let param0): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + return Int32(3) + case .empty: + return Int32(4) + } + } +} + +extension AllTypesResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> AllTypesResult { + switch caseId { + case 0: + return .structPayload(Point.bridgeJSStackPop()) + case 1: + return .classPayload(User.bridgeJSStackPop()) + case 2: + return .jsObjectPayload(JSObject.bridgeJSStackPop()) + case 3: + return .nestedEnum(APIResult.bridgeJSStackPop()) + case 4: + return .arrayPayload([Int].bridgeJSStackPop()) + case 5: + return .empty + default: + fatalError("Unknown AllTypesResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .structPayload(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .classPayload(let param0): + param0.bridgeJSStackPush() + return Int32(1) + case .jsObjectPayload(let param0): + param0.bridgeJSStackPush() + return Int32(2) + case .nestedEnum(let param0): + param0.bridgeJSStackPush() + return Int32(3) + case .arrayPayload(let param0): + param0.bridgeJSStackPush() + return Int32(4) + case .empty: + return Int32(5) + } + } +} + +extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> OptionalAllTypesResult { + switch caseId { + case 0: + return .optStruct(Optional.bridgeJSStackPop()) + case 1: + return .optClass(Optional.bridgeJSStackPop()) + case 2: + return .optJSObject(Optional.bridgeJSStackPop()) + case 3: + return .optNestedEnum(Optional.bridgeJSStackPop()) + case 4: + return .optArray(Optional<[Int]>.bridgeJSStackPop()) + case 5: + return .empty + default: + fatalError("Unknown OptionalAllTypesResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .optStruct(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .optClass(let param0): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + return Int32(1) + case .optJSObject(let param0): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + return Int32(2) + case .optNestedEnum(let param0): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + return Int32(3) + case .optArray(let param0): + param0.bridgeJSStackPush() + return Int32(4) + case .empty: + return Int32(5) + } + } +} + +extension Point: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Point { + let y = Double.bridgeJSStackPop() + let x = Double.bridgeJSStackPop() + return Point(x: x, y: y) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.x.bridgeJSStackPush() + self.y.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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_handle") +@_cdecl("bjs_handle") +public func _bjs_handle(_ result: Int32) -> Void { + #if arch(wasm32) + handle(result: APIResult.bridgeJSLiftParameter(result)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getResult") +@_cdecl("bjs_getResult") +public func _bjs_getResult() -> Void { + #if arch(wasm32) + let ret = getResult() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripAPIResult") +@_cdecl("bjs_roundtripAPIResult") +public func _bjs_roundtripAPIResult(_ result: Int32) -> Void { + #if arch(wasm32) + let ret = roundtripAPIResult(result: APIResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalAPIResult") +@_cdecl("bjs_roundTripOptionalAPIResult") +public func _bjs_roundTripOptionalAPIResult(_ resultIsSome: Int32, _ resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalAPIResult(result: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_handleComplex") +@_cdecl("bjs_handleComplex") +public func _bjs_handleComplex(_ result: Int32) -> Void { + #if arch(wasm32) + handleComplex(result: ComplexResult.bridgeJSLiftParameter(result)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getComplexResult") +@_cdecl("bjs_getComplexResult") +public func _bjs_getComplexResult() -> Void { + #if arch(wasm32) + let ret = getComplexResult() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripComplexResult") +@_cdecl("bjs_roundtripComplexResult") +public func _bjs_roundtripComplexResult(_ result: Int32) -> Void { + #if arch(wasm32) + let ret = roundtripComplexResult(_: ComplexResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalComplexResult") +@_cdecl("bjs_roundTripOptionalComplexResult") +public func _bjs_roundTripOptionalComplexResult(_ resultIsSome: Int32, _ resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalComplexResult(result: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalUtilitiesResult") +@_cdecl("bjs_roundTripOptionalUtilitiesResult") +public func _bjs_roundTripOptionalUtilitiesResult(_ resultIsSome: Int32, _ resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalUtilitiesResult(result: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalNetworkingResult") +@_cdecl("bjs_roundTripOptionalNetworkingResult") +public func _bjs_roundTripOptionalNetworkingResult(_ resultIsSome: Int32, _ resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalNetworkingResult(result: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalAPIOptionalResult") +@_cdecl("bjs_roundTripOptionalAPIOptionalResult") +public func _bjs_roundTripOptionalAPIOptionalResult(_ resultIsSome: Int32, _ resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalAPIOptionalResult(result: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_compareAPIResults") +@_cdecl("bjs_compareAPIResults") +public func _bjs_compareAPIResults(_ result1IsSome: Int32, _ result1CaseId: Int32, _ result2IsSome: Int32, _ result2CaseId: Int32) -> Void { + #if arch(wasm32) + let _tmp_result2 = Optional.bridgeJSLiftParameter(result2IsSome, result2CaseId) + let _tmp_result1 = Optional.bridgeJSLiftParameter(result1IsSome, result1CaseId) + let ret = compareAPIResults(result1: _tmp_result1, result2: _tmp_result2) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripTypedPayloadResult") +@_cdecl("bjs_roundTripTypedPayloadResult") +public func _bjs_roundTripTypedPayloadResult(_ result: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripTypedPayloadResult(_: TypedPayloadResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalTypedPayloadResult") +@_cdecl("bjs_roundTripOptionalTypedPayloadResult") +public func _bjs_roundTripOptionalTypedPayloadResult(_ resultIsSome: Int32, _ resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTypedPayloadResult(_: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripAllTypesResult") +@_cdecl("bjs_roundTripAllTypesResult") +public func _bjs_roundTripAllTypesResult(_ result: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripAllTypesResult(_: AllTypesResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalAllTypesResult") +@_cdecl("bjs_roundTripOptionalAllTypesResult") +public func _bjs_roundTripOptionalAllTypesResult(_ resultIsSome: Int32, _ resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalAllTypesResult(_: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalPayloadResult") +@_cdecl("bjs_roundTripOptionalPayloadResult") +public func _bjs_roundTripOptionalPayloadResult(_ result: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalPayloadResult(_: OptionalAllTypesResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalPayloadResultOpt") +@_cdecl("bjs_roundTripOptionalPayloadResultOpt") +public func _bjs_roundTripOptionalPayloadResultOpt(_ resultIsSome: Int32, _ resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalPayloadResultOpt(_: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_User_deinit") +@_cdecl("bjs_User_deinit") +public func _bjs_User_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension User: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_User_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_User_wrap") +fileprivate func _bjs_User_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_User_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumCase.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumCase.json new file mode 100644 index 000000000..ea32ad739 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumCase.json @@ -0,0 +1,327 @@ +{ + "exported" : { + "classes" : [ + + ], + "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" : "loading" + }, + { + "associatedValues" : [ + + ], + "name" : "success" + }, + { + "associatedValues" : [ + + ], + "name" : "error" + } + ], + "emitStyle" : "const", + "name" : "Status", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Status", + "tsFullPath" : "Status" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "north" + }, + { + "associatedValues" : [ + + ], + "name" : "south" + }, + { + "associatedValues" : [ + + ], + "name" : "east" + }, + { + "associatedValues" : [ + + ], + "name" : "west" + } + ], + "emitStyle" : "tsEnum", + "name" : "TSDirection", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "TSDirection", + "tsFullPath" : "TSDirection" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "success" + } + ], + "emitStyle" : "const", + "explicitAccessControl" : "public", + "name" : "PublicStatus", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "PublicStatus", + "tsFullPath" : "PublicStatus" + } + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_setDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setDirection", + "parameters" : [ + { + "label" : "_", + "name" : "direction", + "type" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getDirection", + "parameters" : [ + + ], + "returnType" : { + "caseEnum" : { + "_0" : "Direction" + } + } + }, + { + "abiName" : "bjs_processDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processDirection", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "Status" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalDirection", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_setTSDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setTSDirection", + "parameters" : [ + { + "label" : "_", + "name" : "direction", + "type" : { + "caseEnum" : { + "_0" : "TSDirection" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getTSDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getTSDirection", + "parameters" : [ + + ], + "returnType" : { + "caseEnum" : { + "_0" : "TSDirection" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalTSDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTSDirection", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "TSDirection" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "TSDirection" + } + }, + "_1" : "null" + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumCase.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumCase.swift new file mode 100644 index 000000000..06c3e1cd8 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumCase.swift @@ -0,0 +1,230 @@ +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: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Status { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Status { + return Status(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .loading + case 1: + self = .success + case 2: + self = .error + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .loading: + return 0 + case .success: + return 1 + case .error: + return 2 + } + } +} + +extension TSDirection: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> TSDirection { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> TSDirection { + return TSDirection(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 PublicStatus: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> PublicStatus { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> PublicStatus { + return PublicStatus(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .success + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .success: + return 0 + } + } +} + +@_expose(wasm, "bjs_setDirection") +@_cdecl("bjs_setDirection") +public func _bjs_setDirection(_ direction: Int32) -> Void { + #if arch(wasm32) + setDirection(_: Direction.bridgeJSLiftParameter(direction)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getDirection") +@_cdecl("bjs_getDirection") +public func _bjs_getDirection() -> Int32 { + #if arch(wasm32) + let ret = getDirection() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processDirection") +@_cdecl("bjs_processDirection") +public func _bjs_processDirection(_ input: Int32) -> Int32 { + #if arch(wasm32) + let ret = processDirection(_: Direction.bridgeJSLiftParameter(input)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalDirection") +@_cdecl("bjs_roundTripOptionalDirection") +public func _bjs_roundTripOptionalDirection(_ inputIsSome: Int32, _ inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalDirection(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setTSDirection") +@_cdecl("bjs_setTSDirection") +public func _bjs_setTSDirection(_ direction: Int32) -> Void { + #if arch(wasm32) + setTSDirection(_: TSDirection.bridgeJSLiftParameter(direction)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getTSDirection") +@_cdecl("bjs_getTSDirection") +public func _bjs_getTSDirection() -> Int32 { + #if arch(wasm32) + let ret = getTSDirection() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalTSDirection") +@_cdecl("bjs_roundTripOptionalTSDirection") +public func _bjs_roundTripOptionalTSDirection(_ inputIsSome: Int32, _ inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTSDirection(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.Global.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.Global.json new file mode 100644 index 000000000..65b8ba350 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.Global.json @@ -0,0 +1,541 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_Converter_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_Converter_toString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "toString", + "namespace" : [ + "Utils" + ], + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "Converter", + "namespace" : [ + "Utils" + ], + "properties" : [ + + ], + "swiftCallName" : "Utils.Converter" + }, + { + "constructor" : { + "abiName" : "bjs_HTTPServer_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_HTTPServer_call", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "call", + "namespace" : [ + "Networking", + "API" + ], + "parameters" : [ + { + "label" : "_", + "name" : "method", + "type" : { + "caseEnum" : { + "_0" : "Networking.API.Method" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "HTTPServer", + "namespace" : [ + "Networking", + "API" + ], + "properties" : [ + + ], + "swiftCallName" : "Networking.API.HTTPServer" + }, + { + "constructor" : { + "abiName" : "bjs_TestServer_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_TestServer_call", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "call", + "namespace" : [ + "Networking", + "APIV2", + "Internal" + ], + "parameters" : [ + { + "label" : "_", + "name" : "method", + "type" : { + "caseEnum" : { + "_0" : "Internal.SupportedMethod" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "TestServer", + "namespace" : [ + "Networking", + "APIV2", + "Internal" + ], + "properties" : [ + + ], + "swiftCallName" : "Internal.TestServer" + } + ], + "enums" : [ + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Utils", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utils", + "tsFullPath" : "Utils" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Networking", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Networking", + "tsFullPath" : "Networking" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "API", + "namespace" : [ + "Networking" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Networking.API", + "tsFullPath" : "Networking.API" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "get" + }, + { + "associatedValues" : [ + + ], + "name" : "post" + }, + { + "associatedValues" : [ + + ], + "name" : "put" + }, + { + "associatedValues" : [ + + ], + "name" : "delete" + } + ], + "emitStyle" : "const", + "name" : "Method", + "namespace" : [ + "Networking", + "API" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Networking.API.Method", + "tsFullPath" : "Networking.API.Method" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Configuration", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Configuration", + "tsFullPath" : "Configuration" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "debug", + "rawValue" : "debug" + }, + { + "associatedValues" : [ + + ], + "name" : "info", + "rawValue" : "info" + }, + { + "associatedValues" : [ + + ], + "name" : "warning", + "rawValue" : "warning" + }, + { + "associatedValues" : [ + + ], + "name" : "error", + "rawValue" : "error" + } + ], + "emitStyle" : "const", + "name" : "LogLevel", + "namespace" : [ + "Configuration" + ], + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Configuration.LogLevel", + "tsFullPath" : "Configuration.LogLevel" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "http", + "rawValue" : "80" + }, + { + "associatedValues" : [ + + ], + "name" : "https", + "rawValue" : "443" + }, + { + "associatedValues" : [ + + ], + "name" : "development", + "rawValue" : "3000" + } + ], + "emitStyle" : "const", + "name" : "Port", + "namespace" : [ + "Configuration" + ], + "rawType" : "Int", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Configuration.Port", + "tsFullPath" : "Configuration.Port" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Internal", + "namespace" : [ + "Networking", + "APIV2" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Internal", + "tsFullPath" : "Networking.APIV2.Internal" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "get" + }, + { + "associatedValues" : [ + + ], + "name" : "post" + } + ], + "emitStyle" : "const", + "name" : "SupportedMethod", + "namespace" : [ + "Networking", + "APIV2", + "Internal" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Internal.SupportedMethod", + "tsFullPath" : "Networking.APIV2.Internal.SupportedMethod" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "GraphOperations", + "namespace" : [ + "Services", + "Graph" + ], + "staticMethods" : [ + { + "abiName" : "bjs_Services_Graph_GraphOperations_static_createGraph", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "createGraph", + "namespace" : [ + "Services", + "Graph", + "GraphOperations" + ], + "parameters" : [ + { + "label" : "rootId", + "name" : "rootId", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "GraphOperations" + } + } + }, + { + "abiName" : "bjs_Services_Graph_GraphOperations_static_nodeCount", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "nodeCount", + "namespace" : [ + "Services", + "Graph", + "GraphOperations" + ], + "parameters" : [ + { + "label" : "graphId", + "name" : "graphId", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "GraphOperations" + } + } + }, + { + "abiName" : "bjs_Services_Graph_GraphOperations_static_validate", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : true + }, + "name" : "validate", + "namespace" : [ + "Services", + "Graph", + "GraphOperations" + ], + "parameters" : [ + { + "label" : "graphId", + "name" : "graphId", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "bool" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "GraphOperations" + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "GraphOperations", + "tsFullPath" : "Services.Graph.GraphOperations" + } + ], + "exposeToGlobal" : true, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.Global.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.Global.swift new file mode 100644 index 000000000..b1b5e9c8c --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.Global.swift @@ -0,0 +1,269 @@ +extension Networking.API.Method: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Networking.API.Method { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Networking.API.Method { + return Networking.API.Method(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .get + case 1: + self = .post + case 2: + self = .put + case 3: + self = .delete + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .get: + return 0 + case .post: + return 1 + case .put: + return 2 + case .delete: + return 3 + } + } +} + +extension Configuration.LogLevel: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Configuration.Port: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Internal.SupportedMethod: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Internal.SupportedMethod { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Internal.SupportedMethod { + return Internal.SupportedMethod(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .get + case 1: + self = .post + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .get: + return 0 + case .post: + return 1 + } + } +} + +@_expose(wasm, "bjs_Services_Graph_GraphOperations_static_createGraph") +@_cdecl("bjs_Services_Graph_GraphOperations_static_createGraph") +public func _bjs_Services_Graph_GraphOperations_static_createGraph(_ rootId: Int32) -> Int32 { + #if arch(wasm32) + let ret = GraphOperations.createGraph(rootId: Int.bridgeJSLiftParameter(rootId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Services_Graph_GraphOperations_static_nodeCount") +@_cdecl("bjs_Services_Graph_GraphOperations_static_nodeCount") +public func _bjs_Services_Graph_GraphOperations_static_nodeCount(_ graphId: Int32) -> Int32 { + #if arch(wasm32) + let ret = GraphOperations.nodeCount(graphId: Int.bridgeJSLiftParameter(graphId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Services_Graph_GraphOperations_static_validate") +@_cdecl("bjs_Services_Graph_GraphOperations_static_validate") +public func _bjs_Services_Graph_GraphOperations_static_validate(_ graphId: Int32) -> Int32 { + #if arch(wasm32) + do { + let ret = try GraphOperations.validate(graphId: Int.bridgeJSLiftParameter(graphId)) + return ret.bridgeJSLowerReturn() + } catch let error { + if let error = error.thrownValue.object { + withExtendedLifetime(error) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } else { + let jsError = JSError(message: String(describing: error)) + withExtendedLifetime(jsError.jsObject) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } + return 0 + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Converter_init") +@_cdecl("bjs_Converter_init") +public func _bjs_Converter_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Utils.Converter() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Converter_toString") +@_cdecl("bjs_Converter_toString") +public func _bjs_Converter_toString(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + let ret = Utils.Converter.bridgeJSLiftParameter(_self).toString(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Converter_deinit") +@_cdecl("bjs_Converter_deinit") +public func _bjs_Converter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Utils.Converter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Converter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Converter_wrap") +fileprivate func _bjs_Converter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Converter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_HTTPServer_init") +@_cdecl("bjs_HTTPServer_init") +public func _bjs_HTTPServer_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Networking.API.HTTPServer() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_HTTPServer_call") +@_cdecl("bjs_HTTPServer_call") +public func _bjs_HTTPServer_call(_ _self: UnsafeMutableRawPointer, _ method: Int32) -> Void { + #if arch(wasm32) + Networking.API.HTTPServer.bridgeJSLiftParameter(_self).call(_: Networking.API.Method.bridgeJSLiftParameter(method)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_HTTPServer_deinit") +@_cdecl("bjs_HTTPServer_deinit") +public func _bjs_HTTPServer_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Networking.API.HTTPServer: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_HTTPServer_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_HTTPServer_wrap") +fileprivate func _bjs_HTTPServer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_HTTPServer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_TestServer_init") +@_cdecl("bjs_TestServer_init") +public func _bjs_TestServer_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Internal.TestServer() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TestServer_call") +@_cdecl("bjs_TestServer_call") +public func _bjs_TestServer_call(_ _self: UnsafeMutableRawPointer, _ method: Int32) -> Void { + #if arch(wasm32) + Internal.TestServer.bridgeJSLiftParameter(_self).call(_: Internal.SupportedMethod.bridgeJSLiftParameter(method)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TestServer_deinit") +@_cdecl("bjs_TestServer_deinit") +public func _bjs_TestServer_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Internal.TestServer: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_TestServer_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_TestServer_wrap") +fileprivate func _bjs_TestServer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_TestServer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.json new file mode 100644 index 000000000..9b800c743 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.json @@ -0,0 +1,541 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_Converter_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_Converter_toString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "toString", + "namespace" : [ + "Utils" + ], + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "Converter", + "namespace" : [ + "Utils" + ], + "properties" : [ + + ], + "swiftCallName" : "Utils.Converter" + }, + { + "constructor" : { + "abiName" : "bjs_HTTPServer_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_HTTPServer_call", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "call", + "namespace" : [ + "Networking", + "API" + ], + "parameters" : [ + { + "label" : "_", + "name" : "method", + "type" : { + "caseEnum" : { + "_0" : "Networking.API.Method" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "HTTPServer", + "namespace" : [ + "Networking", + "API" + ], + "properties" : [ + + ], + "swiftCallName" : "Networking.API.HTTPServer" + }, + { + "constructor" : { + "abiName" : "bjs_TestServer_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_TestServer_call", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "call", + "namespace" : [ + "Networking", + "APIV2", + "Internal" + ], + "parameters" : [ + { + "label" : "_", + "name" : "method", + "type" : { + "caseEnum" : { + "_0" : "Internal.SupportedMethod" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "TestServer", + "namespace" : [ + "Networking", + "APIV2", + "Internal" + ], + "properties" : [ + + ], + "swiftCallName" : "Internal.TestServer" + } + ], + "enums" : [ + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Utils", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utils", + "tsFullPath" : "Utils" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Networking", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Networking", + "tsFullPath" : "Networking" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "API", + "namespace" : [ + "Networking" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Networking.API", + "tsFullPath" : "Networking.API" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "get" + }, + { + "associatedValues" : [ + + ], + "name" : "post" + }, + { + "associatedValues" : [ + + ], + "name" : "put" + }, + { + "associatedValues" : [ + + ], + "name" : "delete" + } + ], + "emitStyle" : "const", + "name" : "Method", + "namespace" : [ + "Networking", + "API" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Networking.API.Method", + "tsFullPath" : "Networking.API.Method" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Configuration", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Configuration", + "tsFullPath" : "Configuration" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "debug", + "rawValue" : "debug" + }, + { + "associatedValues" : [ + + ], + "name" : "info", + "rawValue" : "info" + }, + { + "associatedValues" : [ + + ], + "name" : "warning", + "rawValue" : "warning" + }, + { + "associatedValues" : [ + + ], + "name" : "error", + "rawValue" : "error" + } + ], + "emitStyle" : "const", + "name" : "LogLevel", + "namespace" : [ + "Configuration" + ], + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Configuration.LogLevel", + "tsFullPath" : "Configuration.LogLevel" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "http", + "rawValue" : "80" + }, + { + "associatedValues" : [ + + ], + "name" : "https", + "rawValue" : "443" + }, + { + "associatedValues" : [ + + ], + "name" : "development", + "rawValue" : "3000" + } + ], + "emitStyle" : "const", + "name" : "Port", + "namespace" : [ + "Configuration" + ], + "rawType" : "Int", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Configuration.Port", + "tsFullPath" : "Configuration.Port" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Internal", + "namespace" : [ + "Networking", + "APIV2" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Internal", + "tsFullPath" : "Networking.APIV2.Internal" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "get" + }, + { + "associatedValues" : [ + + ], + "name" : "post" + } + ], + "emitStyle" : "const", + "name" : "SupportedMethod", + "namespace" : [ + "Networking", + "APIV2", + "Internal" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Internal.SupportedMethod", + "tsFullPath" : "Networking.APIV2.Internal.SupportedMethod" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "GraphOperations", + "namespace" : [ + "Services", + "Graph" + ], + "staticMethods" : [ + { + "abiName" : "bjs_Services_Graph_GraphOperations_static_createGraph", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "createGraph", + "namespace" : [ + "Services", + "Graph", + "GraphOperations" + ], + "parameters" : [ + { + "label" : "rootId", + "name" : "rootId", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "GraphOperations" + } + } + }, + { + "abiName" : "bjs_Services_Graph_GraphOperations_static_nodeCount", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "nodeCount", + "namespace" : [ + "Services", + "Graph", + "GraphOperations" + ], + "parameters" : [ + { + "label" : "graphId", + "name" : "graphId", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "GraphOperations" + } + } + }, + { + "abiName" : "bjs_Services_Graph_GraphOperations_static_validate", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : true + }, + "name" : "validate", + "namespace" : [ + "Services", + "Graph", + "GraphOperations" + ], + "parameters" : [ + { + "label" : "graphId", + "name" : "graphId", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "bool" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "GraphOperations" + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "GraphOperations", + "tsFullPath" : "Services.Graph.GraphOperations" + } + ], + "exposeToGlobal" : false, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.swift new file mode 100644 index 000000000..b1b5e9c8c --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.swift @@ -0,0 +1,269 @@ +extension Networking.API.Method: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Networking.API.Method { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Networking.API.Method { + return Networking.API.Method(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .get + case 1: + self = .post + case 2: + self = .put + case 3: + self = .delete + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .get: + return 0 + case .post: + return 1 + case .put: + return 2 + case .delete: + return 3 + } + } +} + +extension Configuration.LogLevel: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Configuration.Port: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Internal.SupportedMethod: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Internal.SupportedMethod { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Internal.SupportedMethod { + return Internal.SupportedMethod(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .get + case 1: + self = .post + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .get: + return 0 + case .post: + return 1 + } + } +} + +@_expose(wasm, "bjs_Services_Graph_GraphOperations_static_createGraph") +@_cdecl("bjs_Services_Graph_GraphOperations_static_createGraph") +public func _bjs_Services_Graph_GraphOperations_static_createGraph(_ rootId: Int32) -> Int32 { + #if arch(wasm32) + let ret = GraphOperations.createGraph(rootId: Int.bridgeJSLiftParameter(rootId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Services_Graph_GraphOperations_static_nodeCount") +@_cdecl("bjs_Services_Graph_GraphOperations_static_nodeCount") +public func _bjs_Services_Graph_GraphOperations_static_nodeCount(_ graphId: Int32) -> Int32 { + #if arch(wasm32) + let ret = GraphOperations.nodeCount(graphId: Int.bridgeJSLiftParameter(graphId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Services_Graph_GraphOperations_static_validate") +@_cdecl("bjs_Services_Graph_GraphOperations_static_validate") +public func _bjs_Services_Graph_GraphOperations_static_validate(_ graphId: Int32) -> Int32 { + #if arch(wasm32) + do { + let ret = try GraphOperations.validate(graphId: Int.bridgeJSLiftParameter(graphId)) + return ret.bridgeJSLowerReturn() + } catch let error { + if let error = error.thrownValue.object { + withExtendedLifetime(error) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } else { + let jsError = JSError(message: String(describing: error)) + withExtendedLifetime(jsError.jsObject) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } + return 0 + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Converter_init") +@_cdecl("bjs_Converter_init") +public func _bjs_Converter_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Utils.Converter() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Converter_toString") +@_cdecl("bjs_Converter_toString") +public func _bjs_Converter_toString(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + let ret = Utils.Converter.bridgeJSLiftParameter(_self).toString(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Converter_deinit") +@_cdecl("bjs_Converter_deinit") +public func _bjs_Converter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Utils.Converter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Converter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Converter_wrap") +fileprivate func _bjs_Converter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Converter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_HTTPServer_init") +@_cdecl("bjs_HTTPServer_init") +public func _bjs_HTTPServer_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Networking.API.HTTPServer() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_HTTPServer_call") +@_cdecl("bjs_HTTPServer_call") +public func _bjs_HTTPServer_call(_ _self: UnsafeMutableRawPointer, _ method: Int32) -> Void { + #if arch(wasm32) + Networking.API.HTTPServer.bridgeJSLiftParameter(_self).call(_: Networking.API.Method.bridgeJSLiftParameter(method)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_HTTPServer_deinit") +@_cdecl("bjs_HTTPServer_deinit") +public func _bjs_HTTPServer_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Networking.API.HTTPServer: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_HTTPServer_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_HTTPServer_wrap") +fileprivate func _bjs_HTTPServer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_HTTPServer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_TestServer_init") +@_cdecl("bjs_TestServer_init") +public func _bjs_TestServer_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Internal.TestServer() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TestServer_call") +@_cdecl("bjs_TestServer_call") +public func _bjs_TestServer_call(_ _self: UnsafeMutableRawPointer, _ method: Int32) -> Void { + #if arch(wasm32) + Internal.TestServer.bridgeJSLiftParameter(_self).call(_: Internal.SupportedMethod.bridgeJSLiftParameter(method)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TestServer_deinit") +@_cdecl("bjs_TestServer_deinit") +public func _bjs_TestServer_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Internal.TestServer: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_TestServer_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_TestServer_wrap") +fileprivate func _bjs_TestServer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_TestServer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumRawType.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumRawType.json new file mode 100644 index 000000000..ba36405ba --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumRawType.json @@ -0,0 +1,1567 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "light", + "rawValue" : "light" + }, + { + "associatedValues" : [ + + ], + "name" : "dark", + "rawValue" : "dark" + }, + { + "associatedValues" : [ + + ], + "name" : "auto", + "rawValue" : "auto" + } + ], + "emitStyle" : "const", + "name" : "Theme", + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Theme", + "tsFullPath" : "Theme" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "light", + "rawValue" : "light" + }, + { + "associatedValues" : [ + + ], + "name" : "dark", + "rawValue" : "dark" + }, + { + "associatedValues" : [ + + ], + "name" : "auto", + "rawValue" : "auto" + } + ], + "emitStyle" : "tsEnum", + "name" : "TSTheme", + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "TSTheme", + "tsFullPath" : "TSTheme" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "enabled", + "rawValue" : "true" + }, + { + "associatedValues" : [ + + ], + "name" : "disabled", + "rawValue" : "false" + } + ], + "emitStyle" : "const", + "name" : "FeatureFlag", + "rawType" : "Bool", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "FeatureFlag", + "tsFullPath" : "FeatureFlag" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "ok", + "rawValue" : "200" + }, + { + "associatedValues" : [ + + ], + "name" : "notFound", + "rawValue" : "404" + }, + { + "associatedValues" : [ + + ], + "name" : "serverError", + "rawValue" : "500" + } + ], + "emitStyle" : "const", + "name" : "HttpStatus", + "rawType" : "Int", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "HttpStatus", + "tsFullPath" : "HttpStatus" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "ok", + "rawValue" : "200" + }, + { + "associatedValues" : [ + + ], + "name" : "notFound", + "rawValue" : "404" + }, + { + "associatedValues" : [ + + ], + "name" : "serverError", + "rawValue" : "500" + } + ], + "emitStyle" : "tsEnum", + "name" : "TSHttpStatus", + "rawType" : "Int", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "TSHttpStatus", + "tsFullPath" : "TSHttpStatus" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "lowest", + "rawValue" : "-1" + }, + { + "associatedValues" : [ + + ], + "name" : "low", + "rawValue" : "2" + }, + { + "associatedValues" : [ + + ], + "name" : "medium", + "rawValue" : "3" + }, + { + "associatedValues" : [ + + ], + "name" : "high", + "rawValue" : "4" + }, + { + "associatedValues" : [ + + ], + "name" : "highest", + "rawValue" : "5" + } + ], + "emitStyle" : "const", + "name" : "Priority", + "rawType" : "Int32", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Priority", + "tsFullPath" : "Priority" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "tiny", + "rawValue" : "1024" + }, + { + "associatedValues" : [ + + ], + "name" : "small", + "rawValue" : "10240" + }, + { + "associatedValues" : [ + + ], + "name" : "medium", + "rawValue" : "102400" + }, + { + "associatedValues" : [ + + ], + "name" : "large", + "rawValue" : "1048576" + } + ], + "emitStyle" : "const", + "name" : "FileSize", + "rawType" : "Int64", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "FileSize", + "tsFullPath" : "FileSize" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "guest", + "rawValue" : "0" + }, + { + "associatedValues" : [ + + ], + "name" : "user", + "rawValue" : "1000" + }, + { + "associatedValues" : [ + + ], + "name" : "admin", + "rawValue" : "9999" + } + ], + "emitStyle" : "const", + "name" : "UserId", + "rawType" : "UInt", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "UserId", + "tsFullPath" : "UserId" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "invalid", + "rawValue" : "0" + }, + { + "associatedValues" : [ + + ], + "name" : "session", + "rawValue" : "12345" + }, + { + "associatedValues" : [ + + ], + "name" : "refresh", + "rawValue" : "67890" + } + ], + "emitStyle" : "const", + "name" : "TokenId", + "rawType" : "UInt32", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "TokenId", + "tsFullPath" : "TokenId" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "none", + "rawValue" : "0" + }, + { + "associatedValues" : [ + + ], + "name" : "active", + "rawValue" : "9876543210" + }, + { + "associatedValues" : [ + + ], + "name" : "expired", + "rawValue" : "1234567890" + } + ], + "emitStyle" : "const", + "name" : "SessionId", + "rawType" : "UInt64", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "SessionId", + "tsFullPath" : "SessionId" + }, + { + "cases" : [ + { + "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" + }, + { + "associatedValues" : [ + + ], + "name" : "pi", + "rawValue" : "3.14159" + } + ], + "emitStyle" : "const", + "name" : "Ratio", + "rawType" : "Double", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Ratio", + "tsFullPath" : "Ratio" + } + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_setTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setTheme", + "parameters" : [ + { + "label" : "_", + "name" : "theme", + "type" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getTheme", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTheme", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_setTSTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setTSTheme", + "parameters" : [ + { + "label" : "_", + "name" : "theme", + "type" : { + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getTSTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getTSTheme", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalTSTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTSTheme", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_setFeatureFlag", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setFeatureFlag", + "parameters" : [ + { + "label" : "_", + "name" : "flag", + "type" : { + "rawValueEnum" : { + "_0" : "FeatureFlag", + "_1" : "String" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getFeatureFlag", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getFeatureFlag", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "FeatureFlag", + "_1" : "String" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalFeatureFlag", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalFeatureFlag", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "FeatureFlag", + "_1" : "String" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "FeatureFlag", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_setHttpStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setHttpStatus", + "parameters" : [ + { + "label" : "_", + "name" : "status", + "type" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getHttpStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getHttpStatus", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalHttpStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalHttpStatus", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_setTSHttpStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setTSHttpStatus", + "parameters" : [ + { + "label" : "_", + "name" : "status", + "type" : { + "rawValueEnum" : { + "_0" : "TSHttpStatus", + "_1" : "Int" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getTSHttpStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getTSHttpStatus", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "TSHttpStatus", + "_1" : "Int" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalHttpStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalHttpStatus", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "TSHttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "TSHttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_setPriority", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setPriority", + "parameters" : [ + { + "label" : "_", + "name" : "priority", + "type" : { + "rawValueEnum" : { + "_0" : "Priority", + "_1" : "Int32" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getPriority", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getPriority", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Priority", + "_1" : "Int32" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalPriority", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalPriority", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Priority", + "_1" : "Int32" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Priority", + "_1" : "Int32" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_setFileSize", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setFileSize", + "parameters" : [ + { + "label" : "_", + "name" : "size", + "type" : { + "rawValueEnum" : { + "_0" : "FileSize", + "_1" : "Int64" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getFileSize", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getFileSize", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "FileSize", + "_1" : "Int64" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalFileSize", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalFileSize", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "FileSize", + "_1" : "Int64" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "FileSize", + "_1" : "Int64" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_setUserId", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setUserId", + "parameters" : [ + { + "label" : "_", + "name" : "id", + "type" : { + "rawValueEnum" : { + "_0" : "UserId", + "_1" : "UInt" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getUserId", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getUserId", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "UserId", + "_1" : "UInt" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalUserId", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalUserId", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "UserId", + "_1" : "UInt" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "UserId", + "_1" : "UInt" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_setTokenId", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setTokenId", + "parameters" : [ + { + "label" : "_", + "name" : "token", + "type" : { + "rawValueEnum" : { + "_0" : "TokenId", + "_1" : "UInt32" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getTokenId", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getTokenId", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "TokenId", + "_1" : "UInt32" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalTokenId", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTokenId", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "TokenId", + "_1" : "UInt32" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "TokenId", + "_1" : "UInt32" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_setSessionId", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setSessionId", + "parameters" : [ + { + "label" : "_", + "name" : "session", + "type" : { + "rawValueEnum" : { + "_0" : "SessionId", + "_1" : "UInt64" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getSessionId", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getSessionId", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "SessionId", + "_1" : "UInt64" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalSessionId", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalSessionId", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "SessionId", + "_1" : "UInt64" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "SessionId", + "_1" : "UInt64" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_setPrecision", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setPrecision", + "parameters" : [ + { + "label" : "_", + "name" : "precision", + "type" : { + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getPrecision", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getPrecision", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalPrecision", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalPrecision", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_setRatio", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setRatio", + "parameters" : [ + { + "label" : "_", + "name" : "ratio", + "type" : { + "rawValueEnum" : { + "_0" : "Ratio", + "_1" : "Double" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getRatio", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getRatio", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Ratio", + "_1" : "Double" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalRatio", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalRatio", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Ratio", + "_1" : "Double" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Ratio", + "_1" : "Double" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_processTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processTheme", + "parameters" : [ + { + "label" : "_", + "name" : "theme", + "type" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + }, + { + "abiName" : "bjs_convertPriority", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "convertPriority", + "parameters" : [ + { + "label" : "_", + "name" : "status", + "type" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Priority", + "_1" : "Int32" + } + } + }, + { + "abiName" : "bjs_validateSession", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "validateSession", + "parameters" : [ + { + "label" : "_", + "name" : "session", + "type" : { + "rawValueEnum" : { + "_0" : "SessionId", + "_1" : "UInt64" + } + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "takesFeatureFlag", + "parameters" : [ + { + "name" : "flag", + "type" : { + "rawValueEnum" : { + "_0" : "FeatureFlag", + "_1" : "String" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "returnsFeatureFlag", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "FeatureFlag", + "_1" : "String" + } + } + } + ], + "types" : [ + + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumRawType.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumRawType.swift new file mode 100644 index 000000000..210361b3b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumRawType.swift @@ -0,0 +1,486 @@ +extension Theme: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension TSTheme: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension FeatureFlag: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension HttpStatus: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension TSHttpStatus: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Priority: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension FileSize: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension UserId: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension TokenId: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension SessionId: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Precision: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Ratio: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +@_expose(wasm, "bjs_setTheme") +@_cdecl("bjs_setTheme") +public func _bjs_setTheme(_ themeBytes: Int32, _ themeLength: Int32) -> Void { + #if arch(wasm32) + setTheme(_: Theme.bridgeJSLiftParameter(themeBytes, themeLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getTheme") +@_cdecl("bjs_getTheme") +public func _bjs_getTheme() -> Void { + #if arch(wasm32) + let ret = getTheme() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalTheme") +@_cdecl("bjs_roundTripOptionalTheme") +public func _bjs_roundTripOptionalTheme(_ inputIsSome: Int32, _ inputBytes: Int32, _ inputLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTheme(_: Optional.bridgeJSLiftParameter(inputIsSome, inputBytes, inputLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setTSTheme") +@_cdecl("bjs_setTSTheme") +public func _bjs_setTSTheme(_ themeBytes: Int32, _ themeLength: Int32) -> Void { + #if arch(wasm32) + setTSTheme(_: TSTheme.bridgeJSLiftParameter(themeBytes, themeLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getTSTheme") +@_cdecl("bjs_getTSTheme") +public func _bjs_getTSTheme() -> Void { + #if arch(wasm32) + let ret = getTSTheme() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalTSTheme") +@_cdecl("bjs_roundTripOptionalTSTheme") +public func _bjs_roundTripOptionalTSTheme(_ inputIsSome: Int32, _ inputBytes: Int32, _ inputLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTSTheme(_: Optional.bridgeJSLiftParameter(inputIsSome, inputBytes, inputLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setFeatureFlag") +@_cdecl("bjs_setFeatureFlag") +public func _bjs_setFeatureFlag(_ flagBytes: Int32, _ flagLength: Int32) -> Void { + #if arch(wasm32) + setFeatureFlag(_: FeatureFlag.bridgeJSLiftParameter(flagBytes, flagLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getFeatureFlag") +@_cdecl("bjs_getFeatureFlag") +public func _bjs_getFeatureFlag() -> Void { + #if arch(wasm32) + let ret = getFeatureFlag() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalFeatureFlag") +@_cdecl("bjs_roundTripOptionalFeatureFlag") +public func _bjs_roundTripOptionalFeatureFlag(_ inputIsSome: Int32, _ inputBytes: Int32, _ inputLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalFeatureFlag(_: Optional.bridgeJSLiftParameter(inputIsSome, inputBytes, inputLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setHttpStatus") +@_cdecl("bjs_setHttpStatus") +public func _bjs_setHttpStatus(_ status: Int32) -> Void { + #if arch(wasm32) + setHttpStatus(_: HttpStatus.bridgeJSLiftParameter(status)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getHttpStatus") +@_cdecl("bjs_getHttpStatus") +public func _bjs_getHttpStatus() -> Int32 { + #if arch(wasm32) + let ret = getHttpStatus() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalHttpStatus") +@_cdecl("bjs_roundTripOptionalHttpStatus") +public func _bjs_roundTripOptionalHttpStatus(_ inputIsSome: Int32, _ inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalHttpStatus(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setTSHttpStatus") +@_cdecl("bjs_setTSHttpStatus") +public func _bjs_setTSHttpStatus(_ status: Int32) -> Void { + #if arch(wasm32) + setTSHttpStatus(_: TSHttpStatus.bridgeJSLiftParameter(status)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getTSHttpStatus") +@_cdecl("bjs_getTSHttpStatus") +public func _bjs_getTSHttpStatus() -> Int32 { + #if arch(wasm32) + let ret = getTSHttpStatus() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalHttpStatus") +@_cdecl("bjs_roundTripOptionalHttpStatus") +public func _bjs_roundTripOptionalHttpStatus(_ inputIsSome: Int32, _ inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalHttpStatus(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setPriority") +@_cdecl("bjs_setPriority") +public func _bjs_setPriority(_ priority: Int32) -> Void { + #if arch(wasm32) + setPriority(_: Priority.bridgeJSLiftParameter(priority)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getPriority") +@_cdecl("bjs_getPriority") +public func _bjs_getPriority() -> Int32 { + #if arch(wasm32) + let ret = getPriority() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalPriority") +@_cdecl("bjs_roundTripOptionalPriority") +public func _bjs_roundTripOptionalPriority(_ inputIsSome: Int32, _ inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalPriority(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setFileSize") +@_cdecl("bjs_setFileSize") +public func _bjs_setFileSize(_ size: Int32) -> Void { + #if arch(wasm32) + setFileSize(_: FileSize.bridgeJSLiftParameter(size)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getFileSize") +@_cdecl("bjs_getFileSize") +public func _bjs_getFileSize() -> Int32 { + #if arch(wasm32) + let ret = getFileSize() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalFileSize") +@_cdecl("bjs_roundTripOptionalFileSize") +public func _bjs_roundTripOptionalFileSize(_ inputIsSome: Int32, _ inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalFileSize(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setUserId") +@_cdecl("bjs_setUserId") +public func _bjs_setUserId(_ id: Int32) -> Void { + #if arch(wasm32) + setUserId(_: UserId.bridgeJSLiftParameter(id)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getUserId") +@_cdecl("bjs_getUserId") +public func _bjs_getUserId() -> Int32 { + #if arch(wasm32) + let ret = getUserId() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalUserId") +@_cdecl("bjs_roundTripOptionalUserId") +public func _bjs_roundTripOptionalUserId(_ inputIsSome: Int32, _ inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalUserId(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setTokenId") +@_cdecl("bjs_setTokenId") +public func _bjs_setTokenId(_ token: Int32) -> Void { + #if arch(wasm32) + setTokenId(_: TokenId.bridgeJSLiftParameter(token)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getTokenId") +@_cdecl("bjs_getTokenId") +public func _bjs_getTokenId() -> Int32 { + #if arch(wasm32) + let ret = getTokenId() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalTokenId") +@_cdecl("bjs_roundTripOptionalTokenId") +public func _bjs_roundTripOptionalTokenId(_ inputIsSome: Int32, _ inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTokenId(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setSessionId") +@_cdecl("bjs_setSessionId") +public func _bjs_setSessionId(_ session: Int32) -> Void { + #if arch(wasm32) + setSessionId(_: SessionId.bridgeJSLiftParameter(session)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getSessionId") +@_cdecl("bjs_getSessionId") +public func _bjs_getSessionId() -> Int32 { + #if arch(wasm32) + let ret = getSessionId() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalSessionId") +@_cdecl("bjs_roundTripOptionalSessionId") +public func _bjs_roundTripOptionalSessionId(_ inputIsSome: Int32, _ inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalSessionId(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setPrecision") +@_cdecl("bjs_setPrecision") +public func _bjs_setPrecision(_ precision: Float32) -> Void { + #if arch(wasm32) + setPrecision(_: Precision.bridgeJSLiftParameter(precision)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getPrecision") +@_cdecl("bjs_getPrecision") +public func _bjs_getPrecision() -> Float32 { + #if arch(wasm32) + let ret = getPrecision() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalPrecision") +@_cdecl("bjs_roundTripOptionalPrecision") +public func _bjs_roundTripOptionalPrecision(_ inputIsSome: Int32, _ inputValue: Float32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalPrecision(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setRatio") +@_cdecl("bjs_setRatio") +public func _bjs_setRatio(_ ratio: Float64) -> Void { + #if arch(wasm32) + setRatio(_: Ratio.bridgeJSLiftParameter(ratio)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getRatio") +@_cdecl("bjs_getRatio") +public func _bjs_getRatio() -> Float64 { + #if arch(wasm32) + let ret = getRatio() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalRatio") +@_cdecl("bjs_roundTripOptionalRatio") +public func _bjs_roundTripOptionalRatio(_ inputIsSome: Int32, _ inputValue: Float64) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalRatio(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processTheme") +@_cdecl("bjs_processTheme") +public func _bjs_processTheme(_ themeBytes: Int32, _ themeLength: Int32) -> Int32 { + #if arch(wasm32) + let ret = processTheme(_: Theme.bridgeJSLiftParameter(themeBytes, themeLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_convertPriority") +@_cdecl("bjs_convertPriority") +public func _bjs_convertPriority(_ status: Int32) -> Int32 { + #if arch(wasm32) + let ret = convertPriority(_: HttpStatus.bridgeJSLiftParameter(status)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_validateSession") +@_cdecl("bjs_validateSession") +public func _bjs_validateSession(_ session: Int32) -> Void { + #if arch(wasm32) + let ret = validateSession(_: SessionId.bridgeJSLiftParameter(session)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_takesFeatureFlag") +fileprivate func bjs_takesFeatureFlag(_ flag: Int32) -> Void +#else +fileprivate func bjs_takesFeatureFlag(_ flag: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$takesFeatureFlag(_ flag: FeatureFlag) throws(JSException) -> Void { + let flagValue = flag.bridgeJSLowerParameter() + bjs_takesFeatureFlag(flagValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_returnsFeatureFlag") +fileprivate func bjs_returnsFeatureFlag() -> Int32 +#else +fileprivate func bjs_returnsFeatureFlag() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$returnsFeatureFlag() throws(JSException) -> FeatureFlag { + let ret = bjs_returnsFeatureFlag() + if let error = _swift_js_take_exception() { + throw error + } + return FeatureFlag.bridgeJSLiftReturn(ret) +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalGetter.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalGetter.json new file mode 100644 index 000000000..55ac7dd70 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalGetter.json @@ -0,0 +1,56 @@ +{ + "imported" : { + "children" : [ + { + "functions" : [ + + ], + "globalGetters" : [ + { + "name" : "console", + "type" : { + "jsObject" : { + "_0" : "JSConsole" + } + } + } + ], + "types" : [ + { + "getters" : [ + + ], + "methods" : [ + { + "name" : "log", + "parameters" : [ + { + "name" : "message", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "JSConsole", + "setters" : [ + + ], + "staticMethods" : [ + + ] + } + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalGetter.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalGetter.swift new file mode 100644 index 000000000..da3f1367b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalGetter.swift @@ -0,0 +1,34 @@ +#if arch(wasm32) +@_extern(wasm, module: "TestModule", 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: "TestModule", 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 + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalThisImports.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalThisImports.json new file mode 100644 index 000000000..5e002e34f --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalThisImports.json @@ -0,0 +1,114 @@ +{ + "imported" : { + "children" : [ + { + "functions" : [ + { + "from" : "global", + "jsName" : "parseInt", + "name" : "parseInt", + "parameters" : [ + { + "name" : "string", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "double" : { + + } + } + } + ], + "globalGetters" : [ + { + "from" : "global", + "name" : "console", + "type" : { + "jsObject" : { + "_0" : "JSConsole" + } + } + } + ], + "types" : [ + { + "getters" : [ + + ], + "methods" : [ + { + "name" : "log", + "parameters" : [ + { + "name" : "message", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "JSConsole", + "setters" : [ + + ], + "staticMethods" : [ + + ] + }, + { + "constructor" : { + "parameters" : [ + { + "name" : "url", + "type" : { + "string" : { + + } + } + } + ] + }, + "from" : "global", + "getters" : [ + + ], + "methods" : [ + { + "name" : "close", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "WebSocket", + "setters" : [ + + ], + "staticMethods" : [ + + ] + } + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalThisImports.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalThisImports.swift new file mode 100644 index 000000000..56353b253 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalThisImports.swift @@ -0,0 +1,87 @@ +#if arch(wasm32) +@_extern(wasm, module: "TestModule", 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: "TestModule", 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: "TestModule", 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: "TestModule", 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: "TestModule", 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__/BridgeJSCodegenTests/ImportArray.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportArray.json new file mode 100644 index 000000000..b884e0cb9 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportArray.json @@ -0,0 +1,62 @@ +{ + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "roundtrip", + "parameters" : [ + { + "name" : "items", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "name" : "logStrings", + "parameters" : [ + { + "name" : "items", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "types" : [ + + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportArray.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportArray.swift new file mode 100644 index 000000000..33b987c76 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportArray.swift @@ -0,0 +1,34 @@ +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_roundtrip") +fileprivate func bjs_roundtrip() -> Void +#else +fileprivate func bjs_roundtrip() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$roundtrip(_ items: [Int]) throws(JSException) -> [Int] { + let _ = items.bridgeJSLowerParameter() + bjs_roundtrip() + if let error = _swift_js_take_exception() { + throw error + } + return [Int].bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_logStrings") +fileprivate func bjs_logStrings() -> Void +#else +fileprivate func bjs_logStrings() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$logStrings(_ items: [String]) throws(JSException) -> Void { + let _ = items.bridgeJSLowerParameter() + bjs_logStrings() + if let error = _swift_js_take_exception() { + throw error + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.json new file mode 100644 index 000000000..f57e77d21 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.json @@ -0,0 +1,202 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_makeFoo", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "makeFoo", + "parameters" : [ + + ], + "returnType" : { + "jsObject" : { + "_0" : "Foo" + } + } + }, + { + "abiName" : "bjs_processFooArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processFooArray", + "parameters" : [ + { + "label" : "_", + "name" : "foos", + "type" : { + "array" : { + "_0" : { + "jsObject" : { + "_0" : "Foo" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "jsObject" : { + "_0" : "Foo" + } + } + } + } + }, + { + "abiName" : "bjs_processOptionalFooArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalFooArray", + "parameters" : [ + { + "label" : "_", + "name" : "foos", + "type" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "jsObject" : { + "_0" : "Foo" + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "jsObject" : { + "_0" : "Foo" + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_roundtripFooContainer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripFooContainer", + "parameters" : [ + { + "label" : "_", + "name" : "container", + "type" : { + "swiftStruct" : { + "_0" : "FooContainer" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "FooContainer" + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + { + "methods" : [ + + ], + "name" : "FooContainer", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "foo", + "type" : { + "jsObject" : { + "_0" : "Foo" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "optionalFoo", + "type" : { + "nullable" : { + "_0" : { + "jsObject" : { + "_0" : "Foo" + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "FooContainer" + } + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + + ], + "types" : [ + { + "constructor" : { + "parameters" : [ + + ] + }, + "getters" : [ + + ], + "methods" : [ + + ], + "name" : "Foo", + "setters" : [ + + ], + "staticMethods" : [ + + ] + } + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift new file mode 100644 index 000000000..7fcc4d3c7 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift @@ -0,0 +1,139 @@ +extension FooContainer: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> FooContainer { + let optionalFoo = Optional.bridgeJSStackPop().map { Foo(unsafelyWrapping: $0) } + let foo = Foo(unsafelyWrapping: JSObject.bridgeJSStackPop()) + return FooContainer(foo: foo, optionalFoo: optionalFoo) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.foo.jsObject.bridgeJSStackPush() + let __bjs_isSome_optionalFoo = self.optionalFoo != nil + if let __bjs_unwrapped_optionalFoo = self.optionalFoo { + __bjs_unwrapped_optionalFoo.jsObject.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_optionalFoo ? 1 : 0) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_FooContainer(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_FooContainer())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_FooContainer") +fileprivate func _bjs_struct_lower_FooContainer(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_FooContainer(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_FooContainer") +fileprivate func _bjs_struct_lift_FooContainer() -> Int32 +#else +fileprivate func _bjs_struct_lift_FooContainer() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_makeFoo") +@_cdecl("bjs_makeFoo") +public func _bjs_makeFoo() -> Int32 { + #if arch(wasm32) + do { + let ret = try makeFoo() + return ret.bridgeJSLowerReturn() + } catch let error { + if let error = error.thrownValue.object { + withExtendedLifetime(error) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } else { + let jsError = JSError(message: String(describing: error)) + withExtendedLifetime(jsError.jsObject) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } + return 0 + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processFooArray") +@_cdecl("bjs_processFooArray") +public func _bjs_processFooArray() -> Void { + #if arch(wasm32) + let ret = processFooArray(_: [JSObject].bridgeJSStackPop().map { Foo(unsafelyWrapping: $0) }) + ret.map { $0.jsObject }.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processOptionalFooArray") +@_cdecl("bjs_processOptionalFooArray") +public func _bjs_processOptionalFooArray() -> Void { + #if arch(wasm32) + let ret = processOptionalFooArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0..<__count { + __result.append(Optional.bridgeJSStackPop().map { Foo(unsafelyWrapping: $0) }) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + let __bjs_isSome_ret_elem = __bjs_elem_ret != nil + if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { + __bjs_unwrapped_ret_elem.jsObject.bridgeJSStackPush() + } + _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_roundtripFooContainer") +@_cdecl("bjs_roundtripFooContainer") +public func _bjs_roundtripFooContainer() -> Void { + #if arch(wasm32) + let ret = roundtripFooContainer(_: FooContainer.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Foo_init") +fileprivate func bjs_Foo_init() -> Int32 +#else +fileprivate func bjs_Foo_init() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$Foo_init() throws(JSException) -> JSObject { + let ret = bjs_Foo_init() + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/InvalidPropertyNames.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/InvalidPropertyNames.json new file mode 100644 index 000000000..935f7a7f2 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/InvalidPropertyNames.json @@ -0,0 +1,246 @@ +{ + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "createWeirdObject", + "parameters" : [ + + ], + "returnType" : { + "jsObject" : { + "_0" : "WeirdNaming" + } + } + }, + { + "name" : "createWeirdClass", + "parameters" : [ + + ], + "returnType" : { + "jsObject" : { + "_0" : "_Weird" + } + } + } + ], + "types" : [ + { + "getters" : [ + { + "name" : "normalProperty", + "type" : { + "string" : { + + } + } + }, + { + "jsName" : "property-with-dashes", + "name" : "property_with_dashes", + "type" : { + "double" : { + + } + } + }, + { + "jsName" : "123invalidStart", + "name" : "_123invalidStart", + "type" : { + "bool" : { + + } + } + }, + { + "jsName" : "property with spaces", + "name" : "property_with_spaces", + "type" : { + "string" : { + + } + } + }, + { + "jsName" : "@specialChar", + "name" : "_specialChar", + "type" : { + "double" : { + + } + } + }, + { + "name" : "constructor", + "type" : { + "string" : { + + } + } + }, + { + "name" : "for", + "type" : { + "string" : { + + } + } + }, + { + "name" : "Any", + "type" : { + "string" : { + + } + } + } + ], + "methods" : [ + { + "name" : "as", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "try", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "WeirdNaming", + "setters" : [ + { + "functionName" : "normalProperty_set", + "name" : "normalProperty", + "type" : { + "string" : { + + } + } + }, + { + "functionName" : "property_with_dashes_set", + "jsName" : "property-with-dashes", + "name" : "property_with_dashes", + "type" : { + "double" : { + + } + } + }, + { + "functionName" : "_123invalidStart_set", + "jsName" : "123invalidStart", + "name" : "_123invalidStart", + "type" : { + "bool" : { + + } + } + }, + { + "functionName" : "property_with_spaces_set", + "jsName" : "property with spaces", + "name" : "property_with_spaces", + "type" : { + "string" : { + + } + } + }, + { + "functionName" : "_specialChar_set", + "jsName" : "@specialChar", + "name" : "_specialChar", + "type" : { + "double" : { + + } + } + }, + { + "functionName" : "constructor_set", + "name" : "constructor", + "type" : { + "string" : { + + } + } + }, + { + "functionName" : "for_set", + "name" : "for", + "type" : { + "string" : { + + } + } + }, + { + "functionName" : "any_set", + "jsName" : "Any", + "name" : "any", + "type" : { + "string" : { + + } + } + } + ], + "staticMethods" : [ + + ] + }, + { + "constructor" : { + "parameters" : [ + + ] + }, + "getters" : [ + + ], + "jsName" : "$Weird", + "methods" : [ + { + "jsName" : "method-with-dashes", + "name" : "method_with_dashes", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "_Weird", + "setters" : [ + + ], + "staticMethods" : [ + + ] + } + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/InvalidPropertyNames.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/InvalidPropertyNames.swift new file mode 100644 index 000000000..86e72bb53 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/InvalidPropertyNames.swift @@ -0,0 +1,389 @@ +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_createWeirdObject") +fileprivate func bjs_createWeirdObject() -> Int32 +#else +fileprivate func bjs_createWeirdObject() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$createWeirdObject() throws(JSException) -> WeirdNaming { + let ret = bjs_createWeirdObject() + if let error = _swift_js_take_exception() { + throw error + } + return WeirdNaming.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", 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: "TestModule", name: "bjs_WeirdNaming_normalProperty_get") +fileprivate func bjs_WeirdNaming_normalProperty_get(_ self: Int32) -> Int32 +#else +fileprivate func bjs_WeirdNaming_normalProperty_get(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", 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: "TestModule", 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: "TestModule", 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: "TestModule", 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: "TestModule", 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: "TestModule", name: "bjs_WeirdNaming_for_get") +fileprivate func bjs_WeirdNaming_for_get(_ self: Int32) -> Int32 +#else +fileprivate func bjs_WeirdNaming_for_get(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WeirdNaming_Any_get") +fileprivate func bjs_WeirdNaming_Any_get(_ self: Int32) -> Int32 +#else +fileprivate func bjs_WeirdNaming_Any_get(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WeirdNaming_normalProperty_set") +fileprivate func bjs_WeirdNaming_normalProperty_set(_ self: Int32, _ newValue: Int32) -> Void +#else +fileprivate func bjs_WeirdNaming_normalProperty_set(_ self: Int32, _ newValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", 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: "TestModule", 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: "TestModule", 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: "TestModule", 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: "TestModule", 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: "TestModule", name: "bjs_WeirdNaming_for_set") +fileprivate func bjs_WeirdNaming_for_set(_ self: Int32, _ newValue: Int32) -> Void +#else +fileprivate func bjs_WeirdNaming_for_set(_ self: Int32, _ newValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WeirdNaming_any_set") +fileprivate func bjs_WeirdNaming_any_set(_ self: Int32, _ newValue: Int32) -> Void +#else +fileprivate func bjs_WeirdNaming_any_set(_ self: Int32, _ newValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WeirdNaming_as") +fileprivate func bjs_WeirdNaming_as(_ self: Int32) -> Void +#else +fileprivate func bjs_WeirdNaming_as(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", 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) + if let error = _swift_js_take_exception() { + throw error + } + 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) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +func _$WeirdNaming_Any_get(_ self: JSObject) throws(JSException) -> String { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_WeirdNaming_Any_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +func _$WeirdNaming_normalProperty_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_WeirdNaming_normalProperty_set(selfValue, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +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() + bjs_WeirdNaming_for_set(selfValue, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$WeirdNaming_any_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_WeirdNaming_any_set(selfValue, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$WeirdNaming_as(_ self: JSObject) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + bjs_WeirdNaming_as(selfValue) + 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: "TestModule", 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: "TestModule", 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__/BridgeJSCodegenTests/JSClass.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClass.json new file mode 100644 index 000000000..689e86150 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClass.json @@ -0,0 +1,160 @@ +{ + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "returnAnimatable", + "parameters" : [ + + ], + "returnType" : { + "jsObject" : { + "_0" : "Animatable" + } + } + } + ], + "types" : [ + { + "constructor" : { + "parameters" : [ + { + "name" : "name", + "type" : { + "string" : { + + } + } + } + ] + }, + "getters" : [ + { + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "name" : "age", + "type" : { + "double" : { + + } + } + } + ], + "methods" : [ + { + "name" : "greet", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "name" : "changeName", + "parameters" : [ + { + "name" : "name", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "Greeter", + "setters" : [ + { + "functionName" : "name_set", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ], + "staticMethods" : [ + + ] + }, + { + "getters" : [ + + ], + "methods" : [ + { + "name" : "animate", + "parameters" : [ + { + "name" : "keyframes", + "type" : { + "jsObject" : { + + } + } + }, + { + "name" : "options", + "type" : { + "jsObject" : { + + } + } + } + ], + "returnType" : { + "jsObject" : { + + } + } + }, + { + "name" : "getAnimations", + "parameters" : [ + { + "name" : "options", + "type" : { + "jsObject" : { + + } + } + } + ], + "returnType" : { + "jsObject" : { + + } + } + } + ], + "name" : "Animatable", + "setters" : [ + + ], + "staticMethods" : [ + + ] + } + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClass.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClass.swift new file mode 100644 index 000000000..09e828fba --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClass.swift @@ -0,0 +1,163 @@ +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_returnAnimatable") +fileprivate func bjs_returnAnimatable() -> Int32 +#else +fileprivate func bjs_returnAnimatable() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$returnAnimatable() throws(JSException) -> Animatable { + let ret = bjs_returnAnimatable() + if let error = _swift_js_take_exception() { + throw error + } + return Animatable.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Greeter_init") +fileprivate func bjs_Greeter_init(_ name: Int32) -> Int32 +#else +fileprivate func bjs_Greeter_init(_ name: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Greeter_name_get") +fileprivate func bjs_Greeter_name_get(_ self: Int32) -> Int32 +#else +fileprivate func bjs_Greeter_name_get(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Greeter_age_get") +fileprivate func bjs_Greeter_age_get(_ self: Int32) -> Float64 +#else +fileprivate func bjs_Greeter_age_get(_ self: Int32) -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Greeter_name_set") +fileprivate func bjs_Greeter_name_set(_ self: Int32, _ newValue: Int32) -> Void +#else +fileprivate func bjs_Greeter_name_set(_ self: Int32, _ newValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Greeter_greet") +fileprivate func bjs_Greeter_greet(_ self: Int32) -> Int32 +#else +fileprivate func bjs_Greeter_greet(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Greeter_changeName") +fileprivate func bjs_Greeter_changeName(_ self: Int32, _ name: Int32) -> Void +#else +fileprivate func bjs_Greeter_changeName(_ self: Int32, _ name: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$Greeter_init(_ name: String) throws(JSException) -> JSObject { + let nameValue = name.bridgeJSLowerParameter() + let ret = bjs_Greeter_init(nameValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + +func _$Greeter_name_get(_ self: JSObject) throws(JSException) -> String { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_Greeter_name_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +func _$Greeter_age_get(_ self: JSObject) throws(JSException) -> Double { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_Greeter_age_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return Double.bridgeJSLiftReturn(ret) +} + +func _$Greeter_name_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_Greeter_name_set(selfValue, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$Greeter_greet(_ self: JSObject) throws(JSException) -> String { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_Greeter_greet(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +func _$Greeter_changeName(_ self: JSObject, _ name: String) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let nameValue = name.bridgeJSLowerParameter() + bjs_Greeter_changeName(selfValue, nameValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Animatable_animate") +fileprivate func bjs_Animatable_animate(_ self: Int32, _ keyframes: Int32, _ options: Int32) -> Int32 +#else +fileprivate func bjs_Animatable_animate(_ self: Int32, _ keyframes: Int32, _ options: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Animatable_getAnimations") +fileprivate func bjs_Animatable_getAnimations(_ self: Int32, _ options: Int32) -> Int32 +#else +fileprivate func bjs_Animatable_getAnimations(_ self: Int32, _ options: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$Animatable_animate(_ self: JSObject, _ keyframes: JSObject, _ options: JSObject) throws(JSException) -> JSObject { + let selfValue = self.bridgeJSLowerParameter() + let keyframesValue = keyframes.bridgeJSLowerParameter() + let optionsValue = options.bridgeJSLowerParameter() + let ret = bjs_Animatable_animate(selfValue, keyframesValue, optionsValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + +func _$Animatable_getAnimations(_ self: JSObject, _ options: JSObject) throws(JSException) -> JSObject { + let selfValue = self.bridgeJSLowerParameter() + let optionsValue = options.bridgeJSLowerParameter() + let ret = bjs_Animatable_getAnimations(selfValue, optionsValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClassStaticFunctions.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClassStaticFunctions.json new file mode 100644 index 000000000..a8b64558f --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClassStaticFunctions.json @@ -0,0 +1,134 @@ +{ + "imported" : { + "children" : [ + { + "functions" : [ + + ], + "types" : [ + { + "getters" : [ + + ], + "methods" : [ + { + "name" : "value", + "parameters" : [ + + ], + "returnType" : { + "double" : { + + } + } + } + ], + "name" : "StaticBox", + "setters" : [ + + ], + "staticMethods" : [ + { + "name" : "create", + "parameters" : [ + { + "name" : "value", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "jsObject" : { + "_0" : "StaticBox" + } + } + }, + { + "name" : "value", + "parameters" : [ + + ], + "returnType" : { + "double" : { + + } + } + }, + { + "name" : "makeDefault", + "parameters" : [ + + ], + "returnType" : { + "jsObject" : { + "_0" : "StaticBox" + } + } + }, + { + "jsName" : "with-dashes", + "name" : "dashed", + "parameters" : [ + + ], + "returnType" : { + "jsObject" : { + "_0" : "StaticBox" + } + } + } + ] + }, + { + "constructor" : { + "parameters" : [ + { + "name" : "value", + "type" : { + "double" : { + + } + } + } + ] + }, + "getters" : [ + + ], + "methods" : [ + + ], + "name" : "WithCtor", + "setters" : [ + + ], + "staticMethods" : [ + { + "name" : "create", + "parameters" : [ + { + "name" : "value", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "jsObject" : { + "_0" : "WithCtor" + } + } + } + ] + } + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClassStaticFunctions.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClassStaticFunctions.swift new file mode 100644 index 000000000..5e297f929 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClassStaticFunctions.swift @@ -0,0 +1,122 @@ +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_StaticBox_create_static") +fileprivate func bjs_StaticBox_create_static(_ value: Float64) -> Int32 +#else +fileprivate func bjs_StaticBox_create_static(_ value: Float64) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_StaticBox_value_static") +fileprivate func bjs_StaticBox_value_static() -> Float64 +#else +fileprivate func bjs_StaticBox_value_static() -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_StaticBox_makeDefault_static") +fileprivate func bjs_StaticBox_makeDefault_static() -> Int32 +#else +fileprivate func bjs_StaticBox_makeDefault_static() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_StaticBox_dashed_static") +fileprivate func bjs_StaticBox_dashed_static() -> Int32 +#else +fileprivate func bjs_StaticBox_dashed_static() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_StaticBox_value") +fileprivate func bjs_StaticBox_value(_ self: Int32) -> Float64 +#else +fileprivate func bjs_StaticBox_value(_ self: Int32) -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$StaticBox_create(_ value: Double) throws(JSException) -> StaticBox { + let valueValue = value.bridgeJSLowerParameter() + let ret = bjs_StaticBox_create_static(valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return StaticBox.bridgeJSLiftReturn(ret) +} + +func _$StaticBox_value() throws(JSException) -> Double { + let ret = bjs_StaticBox_value_static() + if let error = _swift_js_take_exception() { + throw error + } + return Double.bridgeJSLiftReturn(ret) +} + +func _$StaticBox_makeDefault() throws(JSException) -> StaticBox { + let ret = bjs_StaticBox_makeDefault_static() + if let error = _swift_js_take_exception() { + throw error + } + return StaticBox.bridgeJSLiftReturn(ret) +} + +func _$StaticBox_dashed() throws(JSException) -> StaticBox { + let ret = bjs_StaticBox_dashed_static() + if let error = _swift_js_take_exception() { + throw error + } + return StaticBox.bridgeJSLiftReturn(ret) +} + +func _$StaticBox_value(_ self: JSObject) throws(JSException) -> Double { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_StaticBox_value(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return Double.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithCtor_init") +fileprivate func bjs_WithCtor_init(_ value: Float64) -> Int32 +#else +fileprivate func bjs_WithCtor_init(_ value: Float64) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithCtor_create_static") +fileprivate func bjs_WithCtor_create_static(_ value: Float64) -> Int32 +#else +fileprivate func bjs_WithCtor_create_static(_ value: Float64) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$WithCtor_init(_ value: Double) throws(JSException) -> JSObject { + let valueValue = value.bridgeJSLowerParameter() + let ret = bjs_WithCtor_init(valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + +func _$WithCtor_create(_ value: Double) throws(JSException) -> WithCtor { + let valueValue = value.bridgeJSLowerParameter() + let ret = bjs_WithCtor_create_static(valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return WithCtor.bridgeJSLiftReturn(ret) +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.json new file mode 100644 index 000000000..5bd83be27 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.json @@ -0,0 +1,375 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_JSValueHolder_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "jsValue" : { + + } + } + }, + { + "label" : "optionalValue", + "name" : "optionalValue", + "type" : { + "nullable" : { + "_0" : { + "jsValue" : { + + } + }, + "_1" : "null" + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_JSValueHolder_update", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "update", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "jsValue" : { + + } + } + }, + { + "label" : "optionalValue", + "name" : "optionalValue", + "type" : { + "nullable" : { + "_0" : { + "jsValue" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_JSValueHolder_echo", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "echo", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "jsValue" : { + + } + } + } + ], + "returnType" : { + "jsValue" : { + + } + } + }, + { + "abiName" : "bjs_JSValueHolder_echoOptional", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "echoOptional", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "jsValue" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "jsValue" : { + + } + }, + "_1" : "null" + } + } + } + ], + "name" : "JSValueHolder", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "value", + "type" : { + "jsValue" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "optionalValue", + "type" : { + "nullable" : { + "_0" : { + "jsValue" : { + + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "JSValueHolder" + } + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_roundTripJSValue", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripJSValue", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "jsValue" : { + + } + } + } + ], + "returnType" : { + "jsValue" : { + + } + } + }, + { + "abiName" : "bjs_roundTripOptionalJSValue", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalJSValue", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "jsValue" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "jsValue" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripJSValueArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripJSValueArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalJSValueArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalJSValueArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "jsEchoJSValue", + "parameters" : [ + { + "name" : "value", + "type" : { + "jsValue" : { + + } + } + } + ], + "returnType" : { + "jsValue" : { + + } + } + }, + { + "name" : "jsEchoJSValueArray", + "parameters" : [ + { + "name" : "values", + "type" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + } + } + ], + "types" : [ + + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.swift new file mode 100644 index 000000000..41d04ebab --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.swift @@ -0,0 +1,189 @@ +@_expose(wasm, "bjs_roundTripJSValue") +@_cdecl("bjs_roundTripJSValue") +public func _bjs_roundTripJSValue(_ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void { + #if arch(wasm32) + let ret = roundTripJSValue(_: JSValue.bridgeJSLiftParameter(valueKind, valuePayload1, valuePayload2)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalJSValue") +@_cdecl("bjs_roundTripOptionalJSValue") +public func _bjs_roundTripOptionalJSValue(_ valueIsSome: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalJSValue(_: Optional.bridgeJSLiftParameter(valueIsSome, valueKind, valuePayload1, valuePayload2)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripJSValueArray") +@_cdecl("bjs_roundTripJSValueArray") +public func _bjs_roundTripJSValueArray() -> Void { + #if arch(wasm32) + let ret = roundTripJSValueArray(_: [JSValue].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalJSValueArray") +@_cdecl("bjs_roundTripOptionalJSValueArray") +public func _bjs_roundTripOptionalJSValueArray() -> Void { + #if arch(wasm32) + let ret = roundTripOptionalJSValueArray(_: Optional<[JSValue]>.bridgeJSLiftParameter()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_JSValueHolder_init") +@_cdecl("bjs_JSValueHolder_init") +public func _bjs_JSValueHolder_init(_ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64, _ optionalValueIsSome: Int32, _ optionalValueKind: Int32, _ optionalValuePayload1: Int32, _ optionalValuePayload2: Float64) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = JSValueHolder(value: JSValue.bridgeJSLiftParameter(valueKind, valuePayload1, valuePayload2), optionalValue: Optional.bridgeJSLiftParameter(optionalValueIsSome, optionalValueKind, optionalValuePayload1, optionalValuePayload2)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_JSValueHolder_update") +@_cdecl("bjs_JSValueHolder_update") +public func _bjs_JSValueHolder_update(_ _self: UnsafeMutableRawPointer, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64, _ optionalValueIsSome: Int32, _ optionalValueKind: Int32, _ optionalValuePayload1: Int32, _ optionalValuePayload2: Float64) -> Void { + #if arch(wasm32) + JSValueHolder.bridgeJSLiftParameter(_self).update(value: JSValue.bridgeJSLiftParameter(valueKind, valuePayload1, valuePayload2), optionalValue: Optional.bridgeJSLiftParameter(optionalValueIsSome, optionalValueKind, optionalValuePayload1, optionalValuePayload2)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_JSValueHolder_echo") +@_cdecl("bjs_JSValueHolder_echo") +public func _bjs_JSValueHolder_echo(_ _self: UnsafeMutableRawPointer, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void { + #if arch(wasm32) + let ret = JSValueHolder.bridgeJSLiftParameter(_self).echo(value: JSValue.bridgeJSLiftParameter(valueKind, valuePayload1, valuePayload2)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_JSValueHolder_echoOptional") +@_cdecl("bjs_JSValueHolder_echoOptional") +public func _bjs_JSValueHolder_echoOptional(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void { + #if arch(wasm32) + let ret = JSValueHolder.bridgeJSLiftParameter(_self).echoOptional(_: Optional.bridgeJSLiftParameter(valueIsSome, valueKind, valuePayload1, valuePayload2)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_JSValueHolder_value_get") +@_cdecl("bjs_JSValueHolder_value_get") +public func _bjs_JSValueHolder_value_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = JSValueHolder.bridgeJSLiftParameter(_self).value + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_JSValueHolder_value_set") +@_cdecl("bjs_JSValueHolder_value_set") +public func _bjs_JSValueHolder_value_set(_ _self: UnsafeMutableRawPointer, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void { + #if arch(wasm32) + JSValueHolder.bridgeJSLiftParameter(_self).value = JSValue.bridgeJSLiftParameter(valueKind, valuePayload1, valuePayload2) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_JSValueHolder_optionalValue_get") +@_cdecl("bjs_JSValueHolder_optionalValue_get") +public func _bjs_JSValueHolder_optionalValue_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = JSValueHolder.bridgeJSLiftParameter(_self).optionalValue + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_JSValueHolder_optionalValue_set") +@_cdecl("bjs_JSValueHolder_optionalValue_set") +public func _bjs_JSValueHolder_optionalValue_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void { + #if arch(wasm32) + JSValueHolder.bridgeJSLiftParameter(_self).optionalValue = Optional.bridgeJSLiftParameter(valueIsSome, valueKind, valuePayload1, valuePayload2) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_JSValueHolder_deinit") +@_cdecl("bjs_JSValueHolder_deinit") +public func _bjs_JSValueHolder_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension JSValueHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_JSValueHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_JSValueHolder_wrap") +fileprivate func _bjs_JSValueHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_JSValueHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_jsEchoJSValue") +fileprivate func bjs_jsEchoJSValue(_ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void +#else +fileprivate func bjs_jsEchoJSValue(_ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsEchoJSValue(_ value: JSValue) throws(JSException) -> JSValue { + let (valueKind, valuePayload1, valuePayload2) = value.bridgeJSLowerParameter() + bjs_jsEchoJSValue(valueKind, valuePayload1, valuePayload2) + if let error = _swift_js_take_exception() { + throw error + } + return JSValue.bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_jsEchoJSValueArray") +fileprivate func bjs_jsEchoJSValueArray() -> Void +#else +fileprivate func bjs_jsEchoJSValueArray() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsEchoJSValueArray(_ values: [JSValue]) throws(JSException) -> [JSValue] { + let _ = values.bridgeJSLowerParameter() + bjs_jsEchoJSValueArray() + if let error = _swift_js_take_exception() { + throw error + } + return [JSValue].bridgeJSLiftReturn() +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/MixedGlobal.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/MixedGlobal.json new file mode 100644 index 000000000..1241c232d --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/MixedGlobal.json @@ -0,0 +1,79 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_GlobalClass_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_GlobalClass_greet", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "greet", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "GlobalClass", + "namespace" : [ + "GlobalAPI" + ], + "properties" : [ + + ], + "swiftCallName" : "GlobalClass" + } + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_GlobalAPI_globalFunction", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "globalFunction", + "namespace" : [ + "GlobalAPI" + ], + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/MixedGlobal.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/MixedGlobal.swift new file mode 100644 index 000000000..981e01be4 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/MixedGlobal.swift @@ -0,0 +1,57 @@ +@_expose(wasm, "bjs_GlobalAPI_globalFunction") +@_cdecl("bjs_GlobalAPI_globalFunction") +public func _bjs_GlobalAPI_globalFunction() -> Void { + #if arch(wasm32) + let ret = globalFunction() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_GlobalClass_init") +@_cdecl("bjs_GlobalClass_init") +public func _bjs_GlobalClass_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = GlobalClass() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_GlobalClass_greet") +@_cdecl("bjs_GlobalClass_greet") +public func _bjs_GlobalClass_greet(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = GlobalClass.bridgeJSLiftParameter(_self).greet() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_GlobalClass_deinit") +@_cdecl("bjs_GlobalClass_deinit") +public func _bjs_GlobalClass_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension GlobalClass: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_GlobalClass_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_GlobalClass_wrap") +fileprivate func _bjs_GlobalClass_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_GlobalClass_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/MixedPrivate.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/MixedPrivate.json new file mode 100644 index 000000000..96e188fd2 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/MixedPrivate.json @@ -0,0 +1,79 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_PrivateClass_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_PrivateClass_greet", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "greet", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "PrivateClass", + "namespace" : [ + "PrivateAPI" + ], + "properties" : [ + + ], + "swiftCallName" : "PrivateClass" + } + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_PrivateAPI_privateFunction", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "privateFunction", + "namespace" : [ + "PrivateAPI" + ], + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/MixedPrivate.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/MixedPrivate.swift new file mode 100644 index 000000000..1e9eae2bf --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/MixedPrivate.swift @@ -0,0 +1,57 @@ +@_expose(wasm, "bjs_PrivateAPI_privateFunction") +@_cdecl("bjs_PrivateAPI_privateFunction") +public func _bjs_PrivateAPI_privateFunction() -> Void { + #if arch(wasm32) + let ret = privateFunction() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PrivateClass_init") +@_cdecl("bjs_PrivateClass_init") +public func _bjs_PrivateClass_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = PrivateClass() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PrivateClass_greet") +@_cdecl("bjs_PrivateClass_greet") +public func _bjs_PrivateClass_greet(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = PrivateClass.bridgeJSLiftParameter(_self).greet() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PrivateClass_deinit") +@_cdecl("bjs_PrivateClass_deinit") +public func _bjs_PrivateClass_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension PrivateClass: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_PrivateClass_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_PrivateClass_wrap") +fileprivate func _bjs_PrivateClass_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_PrivateClass_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.Global.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.Global.json new file mode 100644 index 000000000..a87bffa6b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.Global.json @@ -0,0 +1,185 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_Greeter_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_Greeter_greet", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "greet", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "Greeter", + "namespace" : [ + "__Swift", + "Foundation" + ], + "properties" : [ + + ], + "swiftCallName" : "Greeter" + }, + { + "constructor" : { + "abiName" : "bjs_Converter_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_Converter_toString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "toString", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "Converter", + "namespace" : [ + "Utils", + "Converters" + ], + "properties" : [ + + ], + "swiftCallName" : "Converter" + }, + { + "methods" : [ + { + "abiName" : "bjs_UUID_uuidString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "uuidString", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "UUID", + "namespace" : [ + "__Swift", + "Foundation" + ], + "properties" : [ + + ], + "swiftCallName" : "UUID" + } + ], + "enums" : [ + + ], + "exposeToGlobal" : true, + "functions" : [ + { + "abiName" : "bjs_plainFunction", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "plainFunction", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_MyModule_Utils_namespacedFunction", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "namespacedFunction", + "namespace" : [ + "MyModule", + "Utils" + ], + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.Global.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.Global.swift new file mode 100644 index 000000000..cb19c6854 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.Global.swift @@ -0,0 +1,151 @@ +@_expose(wasm, "bjs_plainFunction") +@_cdecl("bjs_plainFunction") +public func _bjs_plainFunction() -> Void { + #if arch(wasm32) + let ret = plainFunction() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MyModule_Utils_namespacedFunction") +@_cdecl("bjs_MyModule_Utils_namespacedFunction") +public func _bjs_MyModule_Utils_namespacedFunction() -> Void { + #if arch(wasm32) + let ret = namespacedFunction() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_init") +@_cdecl("bjs_Greeter_init") +public func _bjs_Greeter_init(_ nameBytes: Int32, _ nameLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Greeter(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_greet") +@_cdecl("bjs_Greeter_greet") +public func _bjs_Greeter_greet(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Greeter.bridgeJSLiftParameter(_self).greet() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_deinit") +@_cdecl("bjs_Greeter_deinit") +public func _bjs_Greeter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Greeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Greeter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Greeter_wrap") +fileprivate func _bjs_Greeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Greeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_Converter_init") +@_cdecl("bjs_Converter_init") +public func _bjs_Converter_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Converter() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Converter_toString") +@_cdecl("bjs_Converter_toString") +public func _bjs_Converter_toString(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + let ret = Converter.bridgeJSLiftParameter(_self).toString(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Converter_deinit") +@_cdecl("bjs_Converter_deinit") +public func _bjs_Converter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Converter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Converter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Converter_wrap") +fileprivate func _bjs_Converter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Converter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_UUID_uuidString") +@_cdecl("bjs_UUID_uuidString") +public func _bjs_UUID_uuidString(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = UUID.bridgeJSLiftParameter(_self).uuidString() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_UUID_deinit") +@_cdecl("bjs_UUID_deinit") +public func _bjs_UUID_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension UUID: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_UUID_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_UUID_wrap") +fileprivate func _bjs_UUID_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_UUID_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.json new file mode 100644 index 000000000..766d93a5d --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.json @@ -0,0 +1,185 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_Greeter_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_Greeter_greet", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "greet", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "Greeter", + "namespace" : [ + "__Swift", + "Foundation" + ], + "properties" : [ + + ], + "swiftCallName" : "Greeter" + }, + { + "constructor" : { + "abiName" : "bjs_Converter_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_Converter_toString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "toString", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "Converter", + "namespace" : [ + "Utils", + "Converters" + ], + "properties" : [ + + ], + "swiftCallName" : "Converter" + }, + { + "methods" : [ + { + "abiName" : "bjs_UUID_uuidString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "uuidString", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "UUID", + "namespace" : [ + "__Swift", + "Foundation" + ], + "properties" : [ + + ], + "swiftCallName" : "UUID" + } + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_plainFunction", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "plainFunction", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_MyModule_Utils_namespacedFunction", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "namespacedFunction", + "namespace" : [ + "MyModule", + "Utils" + ], + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.swift new file mode 100644 index 000000000..cb19c6854 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.swift @@ -0,0 +1,151 @@ +@_expose(wasm, "bjs_plainFunction") +@_cdecl("bjs_plainFunction") +public func _bjs_plainFunction() -> Void { + #if arch(wasm32) + let ret = plainFunction() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MyModule_Utils_namespacedFunction") +@_cdecl("bjs_MyModule_Utils_namespacedFunction") +public func _bjs_MyModule_Utils_namespacedFunction() -> Void { + #if arch(wasm32) + let ret = namespacedFunction() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_init") +@_cdecl("bjs_Greeter_init") +public func _bjs_Greeter_init(_ nameBytes: Int32, _ nameLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Greeter(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_greet") +@_cdecl("bjs_Greeter_greet") +public func _bjs_Greeter_greet(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Greeter.bridgeJSLiftParameter(_self).greet() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_deinit") +@_cdecl("bjs_Greeter_deinit") +public func _bjs_Greeter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Greeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Greeter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Greeter_wrap") +fileprivate func _bjs_Greeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Greeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_Converter_init") +@_cdecl("bjs_Converter_init") +public func _bjs_Converter_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Converter() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Converter_toString") +@_cdecl("bjs_Converter_toString") +public func _bjs_Converter_toString(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + let ret = Converter.bridgeJSLiftParameter(_self).toString(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Converter_deinit") +@_cdecl("bjs_Converter_deinit") +public func _bjs_Converter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Converter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Converter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Converter_wrap") +fileprivate func _bjs_Converter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Converter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_UUID_uuidString") +@_cdecl("bjs_UUID_uuidString") +public func _bjs_UUID_uuidString(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = UUID.bridgeJSLiftParameter(_self).uuidString() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_UUID_deinit") +@_cdecl("bjs_UUID_deinit") +public func _bjs_UUID_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension UUID: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_UUID_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_UUID_wrap") +fileprivate func _bjs_UUID_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_UUID_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.json new file mode 100644 index 000000000..9c99bb8c4 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.json @@ -0,0 +1,1233 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_Greeter_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_Greeter_greet", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "greet", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_Greeter_changeName", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "changeName", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "Greeter", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "Greeter" + }, + { + "constructor" : { + "abiName" : "bjs_OptionalPropertyHolder_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + + ], + "name" : "OptionalPropertyHolder", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "optionalName", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "optionalAge", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "optionalGreeter", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "OptionalPropertyHolder" + } + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_roundTripOptionalClass", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalClass", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_testOptionalPropertyRoundtrip", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testOptionalPropertyRoundtrip", + "parameters" : [ + { + "label" : "_", + "name" : "holder", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "OptionalPropertyHolder" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "OptionalPropertyHolder" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripString", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripInt", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripInt", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripBool", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripBool", + "parameters" : [ + { + "label" : "flag", + "name" : "flag", + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripFloat", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripFloat", + "parameters" : [ + { + "label" : "number", + "name" : "number", + "type" : { + "nullable" : { + "_0" : { + "float" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "float" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripDouble", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripDouble", + "parameters" : [ + { + "label" : "precision", + "name" : "precision", + "type" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripSyntax", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripSyntax", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripMixSyntax", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripMixSyntax", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripSwiftSyntax", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripSwiftSyntax", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripMixedSwiftSyntax", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripMixedSwiftSyntax", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripWithSpaces", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripWithSpaces", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripAlias", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripAlias", + "parameters" : [ + { + "label" : "age", + "name" : "age", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalAlias", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalAlias", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_testMixedOptionals", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testMixedOptionals", + "parameters" : [ + { + "label" : "firstName", + "name" : "firstName", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "label" : "lastName", + "name" : "lastName", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "label" : "age", + "name" : "age", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "label" : "active", + "name" : "active", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + + ], + "types" : [ + { + "constructor" : { + "parameters" : [ + { + "name" : "valueOrNull", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "name" : "valueOrUndefined", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "undefined" + } + } + } + ] + }, + "getters" : [ + { + "name" : "stringOrNull", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "name" : "stringOrUndefined", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "undefined" + } + } + }, + { + "name" : "doubleOrNull", + "type" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + }, + { + "name" : "doubleOrUndefined", + "type" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "undefined" + } + } + }, + { + "name" : "boolOrNull", + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + }, + { + "name" : "boolOrUndefined", + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "undefined" + } + } + }, + { + "name" : "intOrNull", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "name" : "intOrUndefined", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "undefined" + } + } + } + ], + "methods" : [ + { + "name" : "roundTripStringOrNull", + "parameters" : [ + { + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "name" : "roundTripStringOrUndefined", + "parameters" : [ + { + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "undefined" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "undefined" + } + } + }, + { + "name" : "roundTripDoubleOrNull", + "parameters" : [ + { + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + }, + { + "name" : "roundTripDoubleOrUndefined", + "parameters" : [ + { + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "undefined" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "undefined" + } + } + }, + { + "name" : "roundTripBoolOrNull", + "parameters" : [ + { + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + }, + { + "name" : "roundTripBoolOrUndefined", + "parameters" : [ + { + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "undefined" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "undefined" + } + } + }, + { + "name" : "roundTripIntOrNull", + "parameters" : [ + { + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "name" : "roundTripIntOrUndefined", + "parameters" : [ + { + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "undefined" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "undefined" + } + } + } + ], + "name" : "WithOptionalJSClass", + "setters" : [ + { + "functionName" : "stringOrNull_set", + "name" : "stringOrNull", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "functionName" : "stringOrUndefined_set", + "name" : "stringOrUndefined", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "undefined" + } + } + }, + { + "functionName" : "doubleOrNull_set", + "name" : "doubleOrNull", + "type" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + }, + { + "functionName" : "doubleOrUndefined_set", + "name" : "doubleOrUndefined", + "type" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "undefined" + } + } + }, + { + "functionName" : "boolOrNull_set", + "name" : "boolOrNull", + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + }, + { + "functionName" : "boolOrUndefined_set", + "name" : "boolOrUndefined", + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "undefined" + } + } + }, + { + "functionName" : "intOrNull_set", + "name" : "intOrNull", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "functionName" : "intOrUndefined_set", + "name" : "intOrUndefined", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "undefined" + } + } + } + ], + "staticMethods" : [ + + ] + } + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.swift new file mode 100644 index 000000000..471d38a6c --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.swift @@ -0,0 +1,800 @@ +@_expose(wasm, "bjs_roundTripOptionalClass") +@_cdecl("bjs_roundTripOptionalClass") +public func _bjs_roundTripOptionalClass(_ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalClass(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testOptionalPropertyRoundtrip") +@_cdecl("bjs_testOptionalPropertyRoundtrip") +public func _bjs_testOptionalPropertyRoundtrip(_ holderIsSome: Int32, _ holderValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = testOptionalPropertyRoundtrip(_: Optional.bridgeJSLiftParameter(holderIsSome, holderValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripString") +@_cdecl("bjs_roundTripString") +public func _bjs_roundTripString(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripString(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripInt") +@_cdecl("bjs_roundTripInt") +public func _bjs_roundTripInt(_ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripInt(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripBool") +@_cdecl("bjs_roundTripBool") +public func _bjs_roundTripBool(_ flagIsSome: Int32, _ flagValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripBool(flag: Optional.bridgeJSLiftParameter(flagIsSome, flagValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripFloat") +@_cdecl("bjs_roundTripFloat") +public func _bjs_roundTripFloat(_ numberIsSome: Int32, _ numberValue: Float32) -> Void { + #if arch(wasm32) + let ret = roundTripFloat(number: Optional.bridgeJSLiftParameter(numberIsSome, numberValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripDouble") +@_cdecl("bjs_roundTripDouble") +public func _bjs_roundTripDouble(_ precisionIsSome: Int32, _ precisionValue: Float64) -> Void { + #if arch(wasm32) + let ret = roundTripDouble(precision: Optional.bridgeJSLiftParameter(precisionIsSome, precisionValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripSyntax") +@_cdecl("bjs_roundTripSyntax") +public func _bjs_roundTripSyntax(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripSyntax(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripMixSyntax") +@_cdecl("bjs_roundTripMixSyntax") +public func _bjs_roundTripMixSyntax(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripMixSyntax(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripSwiftSyntax") +@_cdecl("bjs_roundTripSwiftSyntax") +public func _bjs_roundTripSwiftSyntax(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripSwiftSyntax(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripMixedSwiftSyntax") +@_cdecl("bjs_roundTripMixedSwiftSyntax") +public func _bjs_roundTripMixedSwiftSyntax(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripMixedSwiftSyntax(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripWithSpaces") +@_cdecl("bjs_roundTripWithSpaces") +public func _bjs_roundTripWithSpaces(_ valueIsSome: Int32, _ valueValue: Float64) -> Void { + #if arch(wasm32) + let ret = roundTripWithSpaces(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripAlias") +@_cdecl("bjs_roundTripAlias") +public func _bjs_roundTripAlias(_ ageIsSome: Int32, _ ageValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripAlias(age: Optional.bridgeJSLiftParameter(ageIsSome, ageValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalAlias") +@_cdecl("bjs_roundTripOptionalAlias") +public func _bjs_roundTripOptionalAlias(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalAlias(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testMixedOptionals") +@_cdecl("bjs_testMixedOptionals") +public func _bjs_testMixedOptionals(_ firstNameIsSome: Int32, _ firstNameBytes: Int32, _ firstNameLength: Int32, _ lastNameIsSome: Int32, _ lastNameBytes: Int32, _ lastNameLength: Int32, _ ageIsSome: Int32, _ ageValue: Int32, _ active: Int32) -> Void { + #if arch(wasm32) + let ret = testMixedOptionals(firstName: Optional.bridgeJSLiftParameter(firstNameIsSome, firstNameBytes, firstNameLength), lastName: Optional.bridgeJSLiftParameter(lastNameIsSome, lastNameBytes, lastNameLength), age: Optional.bridgeJSLiftParameter(ageIsSome, ageValue), active: Bool.bridgeJSLiftParameter(active)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_init") +@_cdecl("bjs_Greeter_init") +public func _bjs_Greeter_init(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Greeter(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_greet") +@_cdecl("bjs_Greeter_greet") +public func _bjs_Greeter_greet(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Greeter.bridgeJSLiftParameter(_self).greet() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_changeName") +@_cdecl("bjs_Greeter_changeName") +public func _bjs_Greeter_changeName(_ _self: UnsafeMutableRawPointer, _ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + Greeter.bridgeJSLiftParameter(_self).changeName(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_name_get") +@_cdecl("bjs_Greeter_name_get") +public func _bjs_Greeter_name_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Greeter.bridgeJSLiftParameter(_self).name + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_name_set") +@_cdecl("bjs_Greeter_name_set") +public func _bjs_Greeter_name_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + Greeter.bridgeJSLiftParameter(_self).name = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_deinit") +@_cdecl("bjs_Greeter_deinit") +public func _bjs_Greeter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Greeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Greeter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Greeter_wrap") +fileprivate func _bjs_Greeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Greeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_OptionalPropertyHolder_init") +@_cdecl("bjs_OptionalPropertyHolder_init") +public func _bjs_OptionalPropertyHolder_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = OptionalPropertyHolder() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalName_get") +@_cdecl("bjs_OptionalPropertyHolder_optionalName_get") +public func _bjs_OptionalPropertyHolder_optionalName_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalName + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalName_set") +@_cdecl("bjs_OptionalPropertyHolder_optionalName_set") +public func _bjs_OptionalPropertyHolder_optionalName_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalName = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalAge_get") +@_cdecl("bjs_OptionalPropertyHolder_optionalAge_get") +public func _bjs_OptionalPropertyHolder_optionalAge_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalAge + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalAge_set") +@_cdecl("bjs_OptionalPropertyHolder_optionalAge_set") +public func _bjs_OptionalPropertyHolder_optionalAge_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalAge = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalGreeter_get") +@_cdecl("bjs_OptionalPropertyHolder_optionalGreeter_get") +public func _bjs_OptionalPropertyHolder_optionalGreeter_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalGreeter + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalGreeter_set") +@_cdecl("bjs_OptionalPropertyHolder_optionalGreeter_set") +public func _bjs_OptionalPropertyHolder_optionalGreeter_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalGreeter = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_deinit") +@_cdecl("bjs_OptionalPropertyHolder_deinit") +public func _bjs_OptionalPropertyHolder_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension OptionalPropertyHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_OptionalPropertyHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_OptionalPropertyHolder_wrap") +fileprivate func _bjs_OptionalPropertyHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_OptionalPropertyHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_init") +fileprivate func bjs_WithOptionalJSClass_init(_ valueOrNullIsSome: Int32, _ valueOrNullValue: Int32, _ valueOrUndefinedIsSome: Int32, _ valueOrUndefinedValue: Int32) -> Int32 +#else +fileprivate func bjs_WithOptionalJSClass_init(_ valueOrNullIsSome: Int32, _ valueOrNullValue: Int32, _ valueOrUndefinedIsSome: Int32, _ valueOrUndefinedValue: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_stringOrNull_get") +fileprivate func bjs_WithOptionalJSClass_stringOrNull_get(_ self: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_stringOrNull_get(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_stringOrUndefined_get") +fileprivate func bjs_WithOptionalJSClass_stringOrUndefined_get(_ self: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_stringOrUndefined_get(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_doubleOrNull_get") +fileprivate func bjs_WithOptionalJSClass_doubleOrNull_get(_ self: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_doubleOrNull_get(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_doubleOrUndefined_get") +fileprivate func bjs_WithOptionalJSClass_doubleOrUndefined_get(_ self: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_doubleOrUndefined_get(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_boolOrNull_get") +fileprivate func bjs_WithOptionalJSClass_boolOrNull_get(_ self: Int32) -> Int32 +#else +fileprivate func bjs_WithOptionalJSClass_boolOrNull_get(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_boolOrUndefined_get") +fileprivate func bjs_WithOptionalJSClass_boolOrUndefined_get(_ self: Int32) -> Int32 +#else +fileprivate func bjs_WithOptionalJSClass_boolOrUndefined_get(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_intOrNull_get") +fileprivate func bjs_WithOptionalJSClass_intOrNull_get(_ self: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_intOrNull_get(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_intOrUndefined_get") +fileprivate func bjs_WithOptionalJSClass_intOrUndefined_get(_ self: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_intOrUndefined_get(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_stringOrNull_set") +fileprivate func bjs_WithOptionalJSClass_stringOrNull_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_stringOrNull_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_stringOrUndefined_set") +fileprivate func bjs_WithOptionalJSClass_stringOrUndefined_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_stringOrUndefined_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_doubleOrNull_set") +fileprivate func bjs_WithOptionalJSClass_doubleOrNull_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Float64) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_doubleOrNull_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_doubleOrUndefined_set") +fileprivate func bjs_WithOptionalJSClass_doubleOrUndefined_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Float64) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_doubleOrUndefined_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_boolOrNull_set") +fileprivate func bjs_WithOptionalJSClass_boolOrNull_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_boolOrNull_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_boolOrUndefined_set") +fileprivate func bjs_WithOptionalJSClass_boolOrUndefined_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_boolOrUndefined_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_intOrNull_set") +fileprivate func bjs_WithOptionalJSClass_intOrNull_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_intOrNull_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_intOrUndefined_set") +fileprivate func bjs_WithOptionalJSClass_intOrUndefined_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_intOrUndefined_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_roundTripStringOrNull") +fileprivate func bjs_WithOptionalJSClass_roundTripStringOrNull(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_roundTripStringOrNull(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_roundTripStringOrUndefined") +fileprivate func bjs_WithOptionalJSClass_roundTripStringOrUndefined(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_roundTripStringOrUndefined(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_roundTripDoubleOrNull") +fileprivate func bjs_WithOptionalJSClass_roundTripDoubleOrNull(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Float64) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_roundTripDoubleOrNull(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_roundTripDoubleOrUndefined") +fileprivate func bjs_WithOptionalJSClass_roundTripDoubleOrUndefined(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Float64) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_roundTripDoubleOrUndefined(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_roundTripBoolOrNull") +fileprivate func bjs_WithOptionalJSClass_roundTripBoolOrNull(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Int32 +#else +fileprivate func bjs_WithOptionalJSClass_roundTripBoolOrNull(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_roundTripBoolOrUndefined") +fileprivate func bjs_WithOptionalJSClass_roundTripBoolOrUndefined(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Int32 +#else +fileprivate func bjs_WithOptionalJSClass_roundTripBoolOrUndefined(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_roundTripIntOrNull") +fileprivate func bjs_WithOptionalJSClass_roundTripIntOrNull(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_roundTripIntOrNull(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_roundTripIntOrUndefined") +fileprivate func bjs_WithOptionalJSClass_roundTripIntOrUndefined(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_roundTripIntOrUndefined(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$WithOptionalJSClass_init(_ valueOrNull: Optional, _ valueOrUndefined: JSUndefinedOr) throws(JSException) -> JSObject { + let (valueOrNullIsSome, valueOrNullValue) = valueOrNull.bridgeJSLowerParameter() + let (valueOrUndefinedIsSome, valueOrUndefinedValue) = valueOrUndefined.bridgeJSLowerParameter() + let ret = bjs_WithOptionalJSClass_init(valueOrNullIsSome, valueOrNullValue, valueOrUndefinedIsSome, valueOrUndefinedValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + +func _$WithOptionalJSClass_stringOrNull_get(_ self: JSObject) throws(JSException) -> Optional { + let selfValue = self.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_stringOrNull_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturnFromSideChannel() +} + +func _$WithOptionalJSClass_stringOrUndefined_get(_ self: JSObject) throws(JSException) -> JSUndefinedOr { + let selfValue = self.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_stringOrUndefined_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSUndefinedOr.bridgeJSLiftReturnFromSideChannel() +} + +func _$WithOptionalJSClass_doubleOrNull_get(_ self: JSObject) throws(JSException) -> Optional { + let selfValue = self.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_doubleOrNull_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturnFromSideChannel() +} + +func _$WithOptionalJSClass_doubleOrUndefined_get(_ self: JSObject) throws(JSException) -> JSUndefinedOr { + let selfValue = self.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_doubleOrUndefined_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSUndefinedOr.bridgeJSLiftReturnFromSideChannel() +} + +func _$WithOptionalJSClass_boolOrNull_get(_ self: JSObject) throws(JSException) -> Optional { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_WithOptionalJSClass_boolOrNull_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturn(ret) +} + +func _$WithOptionalJSClass_boolOrUndefined_get(_ self: JSObject) throws(JSException) -> JSUndefinedOr { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_WithOptionalJSClass_boolOrUndefined_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSUndefinedOr.bridgeJSLiftReturn(ret) +} + +func _$WithOptionalJSClass_intOrNull_get(_ self: JSObject) throws(JSException) -> Optional { + let selfValue = self.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_intOrNull_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturnFromSideChannel() +} + +func _$WithOptionalJSClass_intOrUndefined_get(_ self: JSObject) throws(JSException) -> JSUndefinedOr { + let selfValue = self.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_intOrUndefined_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSUndefinedOr.bridgeJSLiftReturnFromSideChannel() +} + +func _$WithOptionalJSClass_stringOrNull_set(_ self: JSObject, _ newValue: Optional) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_stringOrNull_set(selfValue, newValueIsSome, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$WithOptionalJSClass_stringOrUndefined_set(_ self: JSObject, _ newValue: JSUndefinedOr) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_stringOrUndefined_set(selfValue, newValueIsSome, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$WithOptionalJSClass_doubleOrNull_set(_ self: JSObject, _ newValue: Optional) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_doubleOrNull_set(selfValue, newValueIsSome, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$WithOptionalJSClass_doubleOrUndefined_set(_ self: JSObject, _ newValue: JSUndefinedOr) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_doubleOrUndefined_set(selfValue, newValueIsSome, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$WithOptionalJSClass_boolOrNull_set(_ self: JSObject, _ newValue: Optional) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_boolOrNull_set(selfValue, newValueIsSome, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$WithOptionalJSClass_boolOrUndefined_set(_ self: JSObject, _ newValue: JSUndefinedOr) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_boolOrUndefined_set(selfValue, newValueIsSome, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$WithOptionalJSClass_intOrNull_set(_ self: JSObject, _ newValue: Optional) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_intOrNull_set(selfValue, newValueIsSome, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$WithOptionalJSClass_intOrUndefined_set(_ self: JSObject, _ newValue: JSUndefinedOr) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_intOrUndefined_set(selfValue, newValueIsSome, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$WithOptionalJSClass_roundTripStringOrNull(_ self: JSObject, _ value: Optional) throws(JSException) -> Optional { + let selfValue = self.bridgeJSLowerParameter() + let (valueIsSome, valueValue) = value.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_roundTripStringOrNull(selfValue, valueIsSome, valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturnFromSideChannel() +} + +func _$WithOptionalJSClass_roundTripStringOrUndefined(_ self: JSObject, _ value: JSUndefinedOr) throws(JSException) -> JSUndefinedOr { + let selfValue = self.bridgeJSLowerParameter() + let (valueIsSome, valueValue) = value.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_roundTripStringOrUndefined(selfValue, valueIsSome, valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSUndefinedOr.bridgeJSLiftReturnFromSideChannel() +} + +func _$WithOptionalJSClass_roundTripDoubleOrNull(_ self: JSObject, _ value: Optional) throws(JSException) -> Optional { + let selfValue = self.bridgeJSLowerParameter() + let (valueIsSome, valueValue) = value.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_roundTripDoubleOrNull(selfValue, valueIsSome, valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturnFromSideChannel() +} + +func _$WithOptionalJSClass_roundTripDoubleOrUndefined(_ self: JSObject, _ value: JSUndefinedOr) throws(JSException) -> JSUndefinedOr { + let selfValue = self.bridgeJSLowerParameter() + let (valueIsSome, valueValue) = value.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_roundTripDoubleOrUndefined(selfValue, valueIsSome, valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSUndefinedOr.bridgeJSLiftReturnFromSideChannel() +} + +func _$WithOptionalJSClass_roundTripBoolOrNull(_ self: JSObject, _ value: Optional) throws(JSException) -> Optional { + let selfValue = self.bridgeJSLowerParameter() + let (valueIsSome, valueValue) = value.bridgeJSLowerParameter() + let ret = bjs_WithOptionalJSClass_roundTripBoolOrNull(selfValue, valueIsSome, valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturn(ret) +} + +func _$WithOptionalJSClass_roundTripBoolOrUndefined(_ self: JSObject, _ value: JSUndefinedOr) throws(JSException) -> JSUndefinedOr { + let selfValue = self.bridgeJSLowerParameter() + let (valueIsSome, valueValue) = value.bridgeJSLowerParameter() + let ret = bjs_WithOptionalJSClass_roundTripBoolOrUndefined(selfValue, valueIsSome, valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSUndefinedOr.bridgeJSLiftReturn(ret) +} + +func _$WithOptionalJSClass_roundTripIntOrNull(_ self: JSObject, _ value: Optional) throws(JSException) -> Optional { + let selfValue = self.bridgeJSLowerParameter() + let (valueIsSome, valueValue) = value.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_roundTripIntOrNull(selfValue, valueIsSome, valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturnFromSideChannel() +} + +func _$WithOptionalJSClass_roundTripIntOrUndefined(_ self: JSObject, _ value: JSUndefinedOr) throws(JSException) -> JSUndefinedOr { + let selfValue = self.bridgeJSLowerParameter() + let (valueIsSome, valueValue) = value.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_roundTripIntOrUndefined(selfValue, valueIsSome, valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSUndefinedOr.bridgeJSLiftReturnFromSideChannel() +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PrimitiveParameters.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PrimitiveParameters.json new file mode 100644 index 000000000..8b586dbe0 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PrimitiveParameters.json @@ -0,0 +1,118 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_check", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "check", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "int" : { + + } + } + }, + { + "label" : "b", + "name" : "b", + "type" : { + "uint" : { + + } + } + }, + { + "label" : "c", + "name" : "c", + "type" : { + "float" : { + + } + } + }, + { + "label" : "d", + "name" : "d", + "type" : { + "double" : { + + } + } + }, + { + "label" : "e", + "name" : "e", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "check", + "parameters" : [ + { + "name" : "a", + "type" : { + "double" : { + + } + } + }, + { + "name" : "b", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "types" : [ + + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PrimitiveParameters.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PrimitiveParameters.swift new file mode 100644 index 000000000..763cf8ca4 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PrimitiveParameters.swift @@ -0,0 +1,27 @@ +@_expose(wasm, "bjs_check") +@_cdecl("bjs_check") +public func _bjs_check(_ a: Int32, _ b: Int32, _ c: Float32, _ d: Float64, _ e: Int32) -> Void { + #if arch(wasm32) + 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 +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_check") +fileprivate func bjs_check(_ a: Float64, _ b: Int32) -> Void +#else +fileprivate func bjs_check(_ a: Float64, _ b: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$check(_ a: Double, _ b: Bool) throws(JSException) -> Void { + let aValue = a.bridgeJSLowerParameter() + let bValue = b.bridgeJSLowerParameter() + bjs_check(aValue, bValue) + if let error = _swift_js_take_exception() { + throw error + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PrimitiveReturn.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PrimitiveReturn.json new file mode 100644 index 000000000..aae09ea49 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PrimitiveReturn.json @@ -0,0 +1,138 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_checkInt", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "checkInt", + "parameters" : [ + + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_checkUInt", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "checkUInt", + "parameters" : [ + + ], + "returnType" : { + "uint" : { + + } + } + }, + { + "abiName" : "bjs_checkFloat", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "checkFloat", + "parameters" : [ + + ], + "returnType" : { + "float" : { + + } + } + }, + { + "abiName" : "bjs_checkDouble", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "checkDouble", + "parameters" : [ + + ], + "returnType" : { + "double" : { + + } + } + }, + { + "abiName" : "bjs_checkBool", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "checkBool", + "parameters" : [ + + ], + "returnType" : { + "bool" : { + + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "checkNumber", + "parameters" : [ + + ], + "returnType" : { + "double" : { + + } + } + }, + { + "name" : "checkBoolean", + "parameters" : [ + + ], + "returnType" : { + "bool" : { + + } + } + } + ], + "types" : [ + + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PrimitiveReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PrimitiveReturn.swift new file mode 100644 index 000000000..3bbb2809b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PrimitiveReturn.swift @@ -0,0 +1,88 @@ +@_expose(wasm, "bjs_checkInt") +@_cdecl("bjs_checkInt") +public func _bjs_checkInt() -> Int32 { + #if arch(wasm32) + let ret = checkInt() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #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 { + #if arch(wasm32) + let ret = checkFloat() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_checkDouble") +@_cdecl("bjs_checkDouble") +public func _bjs_checkDouble() -> Float64 { + #if arch(wasm32) + let ret = checkDouble() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_checkBool") +@_cdecl("bjs_checkBool") +public func _bjs_checkBool() -> Int32 { + #if arch(wasm32) + let ret = checkBool() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_checkNumber") +fileprivate func bjs_checkNumber() -> Float64 +#else +fileprivate func bjs_checkNumber() -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$checkNumber() throws(JSException) -> Double { + let ret = bjs_checkNumber() + if let error = _swift_js_take_exception() { + throw error + } + return Double.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_checkBoolean") +fileprivate func bjs_checkBoolean() -> Int32 +#else +fileprivate func bjs_checkBoolean() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$checkBoolean() throws(JSException) -> Bool { + let ret = bjs_checkBoolean() + if let error = _swift_js_take_exception() { + throw error + } + return Bool.bridgeJSLiftReturn(ret) +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PropertyTypes.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PropertyTypes.json new file mode 100644 index 000000000..1c71b2b8f --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PropertyTypes.json @@ -0,0 +1,363 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_PropertyHolder_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "intValue", + "name" : "intValue", + "type" : { + "int" : { + + } + } + }, + { + "label" : "floatValue", + "name" : "floatValue", + "type" : { + "float" : { + + } + } + }, + { + "label" : "doubleValue", + "name" : "doubleValue", + "type" : { + "double" : { + + } + } + }, + { + "label" : "boolValue", + "name" : "boolValue", + "type" : { + "bool" : { + + } + } + }, + { + "label" : "stringValue", + "name" : "stringValue", + "type" : { + "string" : { + + } + } + }, + { + "label" : "jsObject", + "name" : "jsObject", + "type" : { + "jsObject" : { + + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_PropertyHolder_getAllValues", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getAllValues", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "PropertyHolder", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "intValue", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "floatValue", + "type" : { + "float" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "doubleValue", + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "boolValue", + "type" : { + "bool" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "stringValue", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "readonlyInt", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "readonlyFloat", + "type" : { + "float" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "readonlyDouble", + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "readonlyBool", + "type" : { + "bool" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "readonlyString", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "jsObject", + "type" : { + "jsObject" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "sibling", + "type" : { + "swiftHeapObject" : { + "_0" : "PropertyHolder" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "lazyValue", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "computedReadonly", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "computedReadWrite", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "observedProperty", + "type" : { + "int" : { + + } + } + } + ], + "swiftCallName" : "PropertyHolder" + } + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_createPropertyHolder", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createPropertyHolder", + "parameters" : [ + { + "label" : "intValue", + "name" : "intValue", + "type" : { + "int" : { + + } + } + }, + { + "label" : "floatValue", + "name" : "floatValue", + "type" : { + "float" : { + + } + } + }, + { + "label" : "doubleValue", + "name" : "doubleValue", + "type" : { + "double" : { + + } + } + }, + { + "label" : "boolValue", + "name" : "boolValue", + "type" : { + "bool" : { + + } + } + }, + { + "label" : "stringValue", + "name" : "stringValue", + "type" : { + "string" : { + + } + } + }, + { + "label" : "jsObject", + "name" : "jsObject", + "type" : { + "jsObject" : { + + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "PropertyHolder" + } + } + }, + { + "abiName" : "bjs_testPropertyHolder", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testPropertyHolder", + "parameters" : [ + { + "label" : "holder", + "name" : "holder", + "type" : { + "swiftHeapObject" : { + "_0" : "PropertyHolder" + } + } + } + ], + "returnType" : { + "string" : { + + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PropertyTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PropertyTypes.swift new file mode 100644 index 000000000..b5b3c8d9e --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PropertyTypes.swift @@ -0,0 +1,344 @@ +@_expose(wasm, "bjs_createPropertyHolder") +@_cdecl("bjs_createPropertyHolder") +public func _bjs_createPropertyHolder(_ intValue: Int32, _ floatValue: Float32, _ doubleValue: Float64, _ boolValue: Int32, _ stringValueBytes: Int32, _ stringValueLength: Int32, _ jsObject: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = createPropertyHolder(intValue: Int.bridgeJSLiftParameter(intValue), floatValue: Float.bridgeJSLiftParameter(floatValue), doubleValue: Double.bridgeJSLiftParameter(doubleValue), boolValue: Bool.bridgeJSLiftParameter(boolValue), stringValue: String.bridgeJSLiftParameter(stringValueBytes, stringValueLength), jsObject: JSObject.bridgeJSLiftParameter(jsObject)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testPropertyHolder") +@_cdecl("bjs_testPropertyHolder") +public func _bjs_testPropertyHolder(_ holder: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = testPropertyHolder(holder: PropertyHolder.bridgeJSLiftParameter(holder)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_init") +@_cdecl("bjs_PropertyHolder_init") +public func _bjs_PropertyHolder_init(_ intValue: Int32, _ floatValue: Float32, _ doubleValue: Float64, _ boolValue: Int32, _ stringValueBytes: Int32, _ stringValueLength: Int32, _ jsObject: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = PropertyHolder(intValue: Int.bridgeJSLiftParameter(intValue), floatValue: Float.bridgeJSLiftParameter(floatValue), doubleValue: Double.bridgeJSLiftParameter(doubleValue), boolValue: Bool.bridgeJSLiftParameter(boolValue), stringValue: String.bridgeJSLiftParameter(stringValueBytes, stringValueLength), jsObject: JSObject.bridgeJSLiftParameter(jsObject)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_getAllValues") +@_cdecl("bjs_PropertyHolder_getAllValues") +public func _bjs_PropertyHolder_getAllValues(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).getAllValues() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_intValue_get") +@_cdecl("bjs_PropertyHolder_intValue_get") +public func _bjs_PropertyHolder_intValue_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).intValue + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_intValue_set") +@_cdecl("bjs_PropertyHolder_intValue_set") +public func _bjs_PropertyHolder_intValue_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).intValue = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_floatValue_get") +@_cdecl("bjs_PropertyHolder_floatValue_get") +public func _bjs_PropertyHolder_floatValue_get(_ _self: UnsafeMutableRawPointer) -> Float32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).floatValue + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_floatValue_set") +@_cdecl("bjs_PropertyHolder_floatValue_set") +public func _bjs_PropertyHolder_floatValue_set(_ _self: UnsafeMutableRawPointer, _ value: Float32) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).floatValue = Float.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_doubleValue_get") +@_cdecl("bjs_PropertyHolder_doubleValue_get") +public func _bjs_PropertyHolder_doubleValue_get(_ _self: UnsafeMutableRawPointer) -> Float64 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).doubleValue + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_doubleValue_set") +@_cdecl("bjs_PropertyHolder_doubleValue_set") +public func _bjs_PropertyHolder_doubleValue_set(_ _self: UnsafeMutableRawPointer, _ value: Float64) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).doubleValue = Double.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_boolValue_get") +@_cdecl("bjs_PropertyHolder_boolValue_get") +public func _bjs_PropertyHolder_boolValue_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).boolValue + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_boolValue_set") +@_cdecl("bjs_PropertyHolder_boolValue_set") +public func _bjs_PropertyHolder_boolValue_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).boolValue = Bool.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_stringValue_get") +@_cdecl("bjs_PropertyHolder_stringValue_get") +public func _bjs_PropertyHolder_stringValue_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).stringValue + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_stringValue_set") +@_cdecl("bjs_PropertyHolder_stringValue_set") +public func _bjs_PropertyHolder_stringValue_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).stringValue = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_readonlyInt_get") +@_cdecl("bjs_PropertyHolder_readonlyInt_get") +public func _bjs_PropertyHolder_readonlyInt_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyInt + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_readonlyFloat_get") +@_cdecl("bjs_PropertyHolder_readonlyFloat_get") +public func _bjs_PropertyHolder_readonlyFloat_get(_ _self: UnsafeMutableRawPointer) -> Float32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyFloat + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_readonlyDouble_get") +@_cdecl("bjs_PropertyHolder_readonlyDouble_get") +public func _bjs_PropertyHolder_readonlyDouble_get(_ _self: UnsafeMutableRawPointer) -> Float64 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyDouble + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_readonlyBool_get") +@_cdecl("bjs_PropertyHolder_readonlyBool_get") +public func _bjs_PropertyHolder_readonlyBool_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyBool + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_readonlyString_get") +@_cdecl("bjs_PropertyHolder_readonlyString_get") +public func _bjs_PropertyHolder_readonlyString_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyString + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_jsObject_get") +@_cdecl("bjs_PropertyHolder_jsObject_get") +public func _bjs_PropertyHolder_jsObject_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_jsObject_set") +@_cdecl("bjs_PropertyHolder_jsObject_set") +public func _bjs_PropertyHolder_jsObject_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).jsObject = JSObject.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_sibling_get") +@_cdecl("bjs_PropertyHolder_sibling_get") +public func _bjs_PropertyHolder_sibling_get(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).sibling + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_sibling_set") +@_cdecl("bjs_PropertyHolder_sibling_set") +public func _bjs_PropertyHolder_sibling_set(_ _self: UnsafeMutableRawPointer, _ value: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).sibling = PropertyHolder.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_lazyValue_get") +@_cdecl("bjs_PropertyHolder_lazyValue_get") +public func _bjs_PropertyHolder_lazyValue_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).lazyValue + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_lazyValue_set") +@_cdecl("bjs_PropertyHolder_lazyValue_set") +public func _bjs_PropertyHolder_lazyValue_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).lazyValue = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_computedReadonly_get") +@_cdecl("bjs_PropertyHolder_computedReadonly_get") +public func _bjs_PropertyHolder_computedReadonly_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).computedReadonly + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_computedReadWrite_get") +@_cdecl("bjs_PropertyHolder_computedReadWrite_get") +public func _bjs_PropertyHolder_computedReadWrite_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).computedReadWrite + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_computedReadWrite_set") +@_cdecl("bjs_PropertyHolder_computedReadWrite_set") +public func _bjs_PropertyHolder_computedReadWrite_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).computedReadWrite = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_observedProperty_get") +@_cdecl("bjs_PropertyHolder_observedProperty_get") +public func _bjs_PropertyHolder_observedProperty_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).observedProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_observedProperty_set") +@_cdecl("bjs_PropertyHolder_observedProperty_set") +public func _bjs_PropertyHolder_observedProperty_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).observedProperty = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_deinit") +@_cdecl("bjs_PropertyHolder_deinit") +public func _bjs_PropertyHolder_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension PropertyHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_PropertyHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_PropertyHolder_wrap") +fileprivate func _bjs_PropertyHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_PropertyHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.json new file mode 100644 index 000000000..e9f5264cd --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.json @@ -0,0 +1,909 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_Helper_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_Helper_increment", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "increment", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "Helper", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "swiftCallName" : "Helper" + }, + { + "constructor" : { + "abiName" : "bjs_MyViewController_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "delegate", + "name" : "delegate", + "type" : { + "swiftProtocol" : { + "_0" : "MyViewControllerDelegate" + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_MyViewController_triggerEvent", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "triggerEvent", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_MyViewController_updateValue", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "updateValue", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_MyViewController_updateCount", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "updateCount", + "parameters" : [ + { + "label" : "_", + "name" : "count", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_MyViewController_updateLabel", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "updateLabel", + "parameters" : [ + { + "label" : "_", + "name" : "prefix", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "suffix", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_MyViewController_checkEvenCount", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "checkEvenCount", + "parameters" : [ + + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_MyViewController_sendHelper", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "sendHelper", + "parameters" : [ + { + "label" : "_", + "name" : "helper", + "type" : { + "swiftHeapObject" : { + "_0" : "Helper" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "MyViewController", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "delegate", + "type" : { + "swiftProtocol" : { + "_0" : "MyViewControllerDelegate" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "secondDelegate", + "type" : { + "nullable" : { + "_0" : { + "swiftProtocol" : { + "_0" : "MyViewControllerDelegate" + } + }, + "_1" : "null" + } + } + } + ], + "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" : [ + { + "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" : "test", + "rawValue" : "test" + }, + { + "associatedValues" : [ + + ], + "name" : "test2", + "rawValue" : "test2" + } + ], + "emitStyle" : "const", + "name" : "ExampleEnum", + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "ExampleEnum", + "tsFullPath" : "ExampleEnum" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + } + ], + "emitStyle" : "const", + "name" : "Result", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Result", + "tsFullPath" : "Result" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "low", + "rawValue" : "-1" + }, + { + "associatedValues" : [ + + ], + "name" : "medium", + "rawValue" : "0" + }, + { + "associatedValues" : [ + + ], + "name" : "high", + "rawValue" : "1" + } + ], + "emitStyle" : "const", + "name" : "Priority", + "rawType" : "Int", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Priority", + "tsFullPath" : "Priority" + } + ], + "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" : [ + { + "methods" : [ + { + "abiName" : "bjs_MyViewControllerDelegate_onSomethingHappened", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "onSomethingHappened", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_MyViewControllerDelegate_onValueChanged", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "onValueChanged", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_MyViewControllerDelegate_onCountUpdated", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "onCountUpdated", + "parameters" : [ + { + "label" : "count", + "name" : "count", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_MyViewControllerDelegate_onLabelUpdated", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "onLabelUpdated", + "parameters" : [ + { + "label" : "_", + "name" : "prefix", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "suffix", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_MyViewControllerDelegate_isCountEven", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "isCountEven", + "parameters" : [ + + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_MyViewControllerDelegate_onHelperUpdated", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "onHelperUpdated", + "parameters" : [ + { + "label" : "_", + "name" : "helper", + "type" : { + "swiftHeapObject" : { + "_0" : "Helper" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_MyViewControllerDelegate_createHelper", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createHelper", + "parameters" : [ + + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Helper" + } + } + }, + { + "abiName" : "bjs_MyViewControllerDelegate_onOptionalHelperUpdated", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "onOptionalHelperUpdated", + "parameters" : [ + { + "label" : "_", + "name" : "helper", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Helper" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_MyViewControllerDelegate_createOptionalHelper", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createOptionalHelper", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Helper" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_MyViewControllerDelegate_createEnum", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createEnum", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "ExampleEnum", + "_1" : "String" + } + } + }, + { + "abiName" : "bjs_MyViewControllerDelegate_handleResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "handleResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "Result" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_MyViewControllerDelegate_getResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getResult", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "Result" + } + } + } + ], + "name" : "MyViewControllerDelegate", + "properties" : [ + { + "isReadonly" : false, + "name" : "eventCount", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "name" : "delegateName", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "name" : "optionalName", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "name" : "optionalRawEnum", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "ExampleEnum", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "name" : "rawStringEnum", + "type" : { + "rawValueEnum" : { + "_0" : "ExampleEnum", + "_1" : "String" + } + } + }, + { + "isReadonly" : false, + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "Result" + } + } + }, + { + "isReadonly" : false, + "name" : "optionalResult", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "Result" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "name" : "direction", + "type" : { + "caseEnum" : { + "_0" : "Direction" + } + } + }, + { + "isReadonly" : false, + "name" : "directionOptional", + "type" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "name" : "priority", + "type" : { + "rawValueEnum" : { + "_0" : "Priority", + "_1" : "Int" + } + } + }, + { + "isReadonly" : false, + "name" : "priorityOptional", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Priority", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + } + ] + } + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift new file mode 100644 index 000000000..65ff9e67c --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift @@ -0,0 +1,675 @@ +struct AnyMyViewControllerDelegate: MyViewControllerDelegate, _BridgedSwiftProtocolWrapper { + let jsObject: JSObject + + func onSomethingHappened() -> Void { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + _extern_onSomethingHappened(jsObjectValue) + } + + func onValueChanged(_ value: String) -> Void { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let valueValue = value.bridgeJSLowerParameter() + _extern_onValueChanged(jsObjectValue, valueValue) + } + + func onCountUpdated(count: Int) -> Bool { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let countValue = count.bridgeJSLowerParameter() + let ret = _extern_onCountUpdated(jsObjectValue, countValue) + return Bool.bridgeJSLiftReturn(ret) + } + + func onLabelUpdated(_ prefix: String, _ suffix: String) -> Void { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let prefixValue = prefix.bridgeJSLowerParameter() + let suffixValue = suffix.bridgeJSLowerParameter() + _extern_onLabelUpdated(jsObjectValue, prefixValue, suffixValue) + } + + func isCountEven() -> Bool { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = _extern_isCountEven(jsObjectValue) + return Bool.bridgeJSLiftReturn(ret) + } + + func onHelperUpdated(_ helper: Helper) -> Void { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let helperPointer = helper.bridgeJSLowerParameter() + _extern_onHelperUpdated(jsObjectValue, helperPointer) + } + + func createHelper() -> Helper { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = _extern_createHelper(jsObjectValue) + return Helper.bridgeJSLiftReturn(ret) + } + + func onOptionalHelperUpdated(_ helper: Optional) -> Void { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let (helperIsSome, helperPointer) = helper.bridgeJSLowerParameter() + _extern_onOptionalHelperUpdated(jsObjectValue, helperIsSome, helperPointer) + } + + func createOptionalHelper() -> Optional { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = _extern_createOptionalHelper(jsObjectValue) + return Optional.bridgeJSLiftReturn(ret) + } + + func createEnum() -> ExampleEnum { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = _extern_createEnum(jsObjectValue) + return ExampleEnum.bridgeJSLiftReturn(ret) + } + + func handleResult(_ result: Result) -> Void { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let resultCaseId = result.bridgeJSLowerParameter() + _extern_handleResult(jsObjectValue, resultCaseId) + } + + func getResult() -> Result { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = _extern_getResult(jsObjectValue) + return Result.bridgeJSLiftReturn(ret) + } + + var eventCount: Int { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = bjs_MyViewControllerDelegate_eventCount_get(jsObjectValue) + return Int.bridgeJSLiftReturn(ret) + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_MyViewControllerDelegate_eventCount_set(jsObjectValue, newValueValue) + } + } + + var delegateName: String { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = bjs_MyViewControllerDelegate_delegateName_get(jsObjectValue) + return String.bridgeJSLiftReturn(ret) + } + } + + var optionalName: Optional { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + bjs_MyViewControllerDelegate_optionalName_get(jsObjectValue) + return Optional.bridgeJSLiftReturnFromSideChannel() + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_MyViewControllerDelegate_optionalName_set(jsObjectValue, newValueIsSome, newValueValue) + } + } + + var optionalRawEnum: Optional { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + bjs_MyViewControllerDelegate_optionalRawEnum_get(jsObjectValue) + return Optional.bridgeJSLiftReturnFromSideChannel() + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_MyViewControllerDelegate_optionalRawEnum_set(jsObjectValue, newValueIsSome, newValueValue) + } + } + + var rawStringEnum: ExampleEnum { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = bjs_MyViewControllerDelegate_rawStringEnum_get(jsObjectValue) + return ExampleEnum.bridgeJSLiftReturn(ret) + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_MyViewControllerDelegate_rawStringEnum_set(jsObjectValue, newValueValue) + } + } + + var result: Result { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = bjs_MyViewControllerDelegate_result_get(jsObjectValue) + return Result.bridgeJSLiftReturn(ret) + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let newValueCaseId = newValue.bridgeJSLowerParameter() + bjs_MyViewControllerDelegate_result_set(jsObjectValue, newValueCaseId) + } + } + + var optionalResult: Optional { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = bjs_MyViewControllerDelegate_optionalResult_get(jsObjectValue) + return Optional.bridgeJSLiftReturn(ret) + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let (newValueIsSome, newValueCaseId) = newValue.bridgeJSLowerParameter() + bjs_MyViewControllerDelegate_optionalResult_set(jsObjectValue, newValueIsSome, newValueCaseId) + } + } + + var direction: Direction { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = bjs_MyViewControllerDelegate_direction_get(jsObjectValue) + return Direction.bridgeJSLiftReturn(ret) + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_MyViewControllerDelegate_direction_set(jsObjectValue, newValueValue) + } + } + + var directionOptional: Optional { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = bjs_MyViewControllerDelegate_directionOptional_get(jsObjectValue) + return Optional.bridgeJSLiftReturn(ret) + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_MyViewControllerDelegate_directionOptional_set(jsObjectValue, newValueIsSome, newValueValue) + } + } + + var priority: Priority { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = bjs_MyViewControllerDelegate_priority_get(jsObjectValue) + return Priority.bridgeJSLiftReturn(ret) + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_MyViewControllerDelegate_priority_set(jsObjectValue, newValueValue) + } + } + + var priorityOptional: Optional { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + bjs_MyViewControllerDelegate_priorityOptional_get(jsObjectValue) + return Optional.bridgeJSLiftReturnFromSideChannel() + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_MyViewControllerDelegate_priorityOptional_set(jsObjectValue, newValueIsSome, newValueValue) + } + } + + static func bridgeJSLiftParameter(_ value: Int32) -> Self { + return AnyMyViewControllerDelegate(jsObject: JSObject(id: UInt32(bitPattern: value))) + } +} + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_onSomethingHappened") +fileprivate func _extern_onSomethingHappened(_ jsObject: Int32) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_onValueChanged") +fileprivate func _extern_onValueChanged(_ jsObject: Int32, _ value: Int32) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_onCountUpdated") +fileprivate func _extern_onCountUpdated(_ jsObject: Int32, _ count: Int32) -> Int32 + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_onLabelUpdated") +fileprivate func _extern_onLabelUpdated(_ jsObject: Int32, _ prefix: Int32, _ suffix: Int32) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_isCountEven") +fileprivate func _extern_isCountEven(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_onHelperUpdated") +fileprivate func _extern_onHelperUpdated(_ jsObject: Int32, _ helper: UnsafeMutableRawPointer) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_createHelper") +fileprivate func _extern_createHelper(_ jsObject: Int32) -> UnsafeMutableRawPointer + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_onOptionalHelperUpdated") +fileprivate func _extern_onOptionalHelperUpdated(_ jsObject: Int32, _ helperIsSome: Int32, _ helperPointer: UnsafeMutableRawPointer) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_createOptionalHelper") +fileprivate func _extern_createOptionalHelper(_ jsObject: Int32) -> UnsafeMutableRawPointer + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_createEnum") +fileprivate func _extern_createEnum(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_handleResult") +fileprivate func _extern_handleResult(_ jsObject: Int32, _ result: Int32) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_getResult") +fileprivate func _extern_getResult(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_eventCount_get") +fileprivate func bjs_MyViewControllerDelegate_eventCount_get(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_eventCount_set") +fileprivate func bjs_MyViewControllerDelegate_eventCount_set(_ jsObject: Int32, _ newValue: Int32) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_delegateName_get") +fileprivate func bjs_MyViewControllerDelegate_delegateName_get(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_optionalName_get") +fileprivate func bjs_MyViewControllerDelegate_optionalName_get(_ jsObject: Int32) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_optionalName_set") +fileprivate func bjs_MyViewControllerDelegate_optionalName_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_optionalRawEnum_get") +fileprivate func bjs_MyViewControllerDelegate_optionalRawEnum_get(_ jsObject: Int32) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_optionalRawEnum_set") +fileprivate func bjs_MyViewControllerDelegate_optionalRawEnum_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_rawStringEnum_get") +fileprivate func bjs_MyViewControllerDelegate_rawStringEnum_get(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_rawStringEnum_set") +fileprivate func bjs_MyViewControllerDelegate_rawStringEnum_set(_ jsObject: Int32, _ newValue: Int32) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_result_get") +fileprivate func bjs_MyViewControllerDelegate_result_get(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_result_set") +fileprivate func bjs_MyViewControllerDelegate_result_set(_ jsObject: Int32, _ newValue: Int32) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_optionalResult_get") +fileprivate func bjs_MyViewControllerDelegate_optionalResult_get(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_optionalResult_set") +fileprivate func bjs_MyViewControllerDelegate_optionalResult_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueCaseId: Int32) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_direction_get") +fileprivate func bjs_MyViewControllerDelegate_direction_get(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_direction_set") +fileprivate func bjs_MyViewControllerDelegate_direction_set(_ jsObject: Int32, _ newValue: Int32) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_directionOptional_get") +fileprivate func bjs_MyViewControllerDelegate_directionOptional_get(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_directionOptional_set") +fileprivate func bjs_MyViewControllerDelegate_directionOptional_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_priority_get") +fileprivate func bjs_MyViewControllerDelegate_priority_get(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_priority_set") +fileprivate func bjs_MyViewControllerDelegate_priority_set(_ jsObject: Int32, _ newValue: Int32) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_priorityOptional_get") +fileprivate func bjs_MyViewControllerDelegate_priorityOptional_get(_ jsObject: Int32) -> Void + +@_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_priorityOptional_set") +fileprivate func bjs_MyViewControllerDelegate_priorityOptional_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void + +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 ExampleEnum: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Result: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> Result { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(Int.bridgeJSStackPop()) + default: + fatalError("Unknown Result case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .failure(let param0): + param0.bridgeJSStackPush() + return Int32(1) + } + } +} + +extension Priority: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +@_expose(wasm, "bjs_processDelegates") +@_cdecl("bjs_processDelegates") +public func _bjs_processDelegates() -> Void { + #if arch(wasm32) + let ret = processDelegates(_: [AnyMyViewControllerDelegate].bridgeJSStackPop()) + ret.map { $0 as! AnyMyViewControllerDelegate }.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Helper_init") +@_cdecl("bjs_Helper_init") +public func _bjs_Helper_init(_ value: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Helper(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Helper_increment") +@_cdecl("bjs_Helper_increment") +public func _bjs_Helper_increment(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Helper.bridgeJSLiftParameter(_self).increment() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Helper_value_get") +@_cdecl("bjs_Helper_value_get") +public func _bjs_Helper_value_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = Helper.bridgeJSLiftParameter(_self).value + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Helper_value_set") +@_cdecl("bjs_Helper_value_set") +public func _bjs_Helper_value_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + Helper.bridgeJSLiftParameter(_self).value = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Helper_deinit") +@_cdecl("bjs_Helper_deinit") +public func _bjs_Helper_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Helper: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Helper_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Helper_wrap") +fileprivate func _bjs_Helper_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Helper_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_MyViewController_init") +@_cdecl("bjs_MyViewController_init") +public func _bjs_MyViewController_init(_ delegate: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = MyViewController(delegate: AnyMyViewControllerDelegate.bridgeJSLiftParameter(delegate)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MyViewController_triggerEvent") +@_cdecl("bjs_MyViewController_triggerEvent") +public func _bjs_MyViewController_triggerEvent(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + MyViewController.bridgeJSLiftParameter(_self).triggerEvent() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MyViewController_updateValue") +@_cdecl("bjs_MyViewController_updateValue") +public func _bjs_MyViewController_updateValue(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + MyViewController.bridgeJSLiftParameter(_self).updateValue(_: String.bridgeJSLiftParameter(valueBytes, valueLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MyViewController_updateCount") +@_cdecl("bjs_MyViewController_updateCount") +public func _bjs_MyViewController_updateCount(_ _self: UnsafeMutableRawPointer, _ count: Int32) -> Int32 { + #if arch(wasm32) + let ret = MyViewController.bridgeJSLiftParameter(_self).updateCount(_: Int.bridgeJSLiftParameter(count)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MyViewController_updateLabel") +@_cdecl("bjs_MyViewController_updateLabel") +public func _bjs_MyViewController_updateLabel(_ _self: UnsafeMutableRawPointer, _ prefixBytes: Int32, _ prefixLength: Int32, _ suffixBytes: Int32, _ suffixLength: Int32) -> Void { + #if arch(wasm32) + MyViewController.bridgeJSLiftParameter(_self).updateLabel(_: String.bridgeJSLiftParameter(prefixBytes, prefixLength), _: String.bridgeJSLiftParameter(suffixBytes, suffixLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MyViewController_checkEvenCount") +@_cdecl("bjs_MyViewController_checkEvenCount") +public func _bjs_MyViewController_checkEvenCount(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = MyViewController.bridgeJSLiftParameter(_self).checkEvenCount() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MyViewController_sendHelper") +@_cdecl("bjs_MyViewController_sendHelper") +public func _bjs_MyViewController_sendHelper(_ _self: UnsafeMutableRawPointer, _ helper: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + MyViewController.bridgeJSLiftParameter(_self).sendHelper(_: Helper.bridgeJSLiftParameter(helper)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MyViewController_delegate_get") +@_cdecl("bjs_MyViewController_delegate_get") +public func _bjs_MyViewController_delegate_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = MyViewController.bridgeJSLiftParameter(_self).delegate as! AnyMyViewControllerDelegate + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MyViewController_delegate_set") +@_cdecl("bjs_MyViewController_delegate_set") +public func _bjs_MyViewController_delegate_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + MyViewController.bridgeJSLiftParameter(_self).delegate = AnyMyViewControllerDelegate.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MyViewController_secondDelegate_get") +@_cdecl("bjs_MyViewController_secondDelegate_get") +public func _bjs_MyViewController_secondDelegate_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = (MyViewController.bridgeJSLiftParameter(_self).secondDelegate).flatMap { $0 as? AnyMyViewControllerDelegate } + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MyViewController_secondDelegate_set") +@_cdecl("bjs_MyViewController_secondDelegate_set") +public func _bjs_MyViewController_secondDelegate_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + MyViewController.bridgeJSLiftParameter(_self).secondDelegate = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MyViewController_deinit") +@_cdecl("bjs_MyViewController_deinit") +public func _bjs_MyViewController_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension MyViewController: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_MyViewController_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_MyViewController_wrap") +fileprivate func _bjs_MyViewController_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +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: [AnyMyViewControllerDelegate].bridgeJSStackPop()) + 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 + ret.map { $0 as! AnyMyViewControllerDelegate }.bridgeJSStackPush() + #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 = [AnyMyViewControllerDelegate].bridgeJSStackPop() + #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__/BridgeJSCodegenTests/StaticFunctions.Global.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.Global.json new file mode 100644 index 000000000..b0eac3313 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.Global.json @@ -0,0 +1,339 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_MathUtils_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_MathUtils_static_subtract", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "subtract", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "int" : { + + } + } + }, + { + "label" : "b", + "name" : "b", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "className" : { + "_0" : "MathUtils" + } + } + }, + { + "abiName" : "bjs_MathUtils_static_add", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "add", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "int" : { + + } + } + }, + { + "label" : "b", + "name" : "b", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "className" : { + "_0" : "MathUtils" + } + } + }, + { + "abiName" : "bjs_MathUtils_multiply", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "multiply", + "parameters" : [ + { + "label" : "x", + "name" : "x", + "type" : { + "int" : { + + } + } + }, + { + "label" : "y", + "name" : "y", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + } + } + ], + "name" : "MathUtils", + "properties" : [ + + ], + "swiftCallName" : "MathUtils" + } + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "scientific" + }, + { + "associatedValues" : [ + + ], + "name" : "basic" + } + ], + "emitStyle" : "const", + "name" : "Calculator", + "staticMethods" : [ + { + "abiName" : "bjs_Calculator_static_square", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "square", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "enumName" : { + "_0" : "Calculator" + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Calculator", + "tsFullPath" : "Calculator" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + } + ], + "emitStyle" : "const", + "name" : "APIResult", + "staticMethods" : [ + { + "abiName" : "bjs_APIResult_static_roundtrip", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "roundtrip", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "staticContext" : { + "enumName" : { + "_0" : "APIResult" + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "APIResult", + "tsFullPath" : "APIResult" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Utils", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utils", + "tsFullPath" : "Utils" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "String", + "namespace" : [ + "Utils" + ], + "staticMethods" : [ + { + "abiName" : "bjs_Utils_String_static_uppercase", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "uppercase", + "namespace" : [ + "Utils", + "String" + ], + "parameters" : [ + { + "label" : "_", + "name" : "text", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "Utils.String" + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utils.String", + "tsFullPath" : "Utils.String" + } + ], + "exposeToGlobal" : true, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.Global.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.Global.swift new file mode 100644 index 000000000..8ad34d283 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.Global.swift @@ -0,0 +1,160 @@ +extension Calculator: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Calculator { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Calculator { + return Calculator(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .scientific + case 1: + self = .basic + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .scientific: + return 0 + case .basic: + return 1 + } + } +} + +@_expose(wasm, "bjs_Calculator_static_square") +@_cdecl("bjs_Calculator_static_square") +public func _bjs_Calculator_static_square(_ value: Int32) -> Int32 { + #if arch(wasm32) + let ret = Calculator.square(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension APIResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> APIResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(Int.bridgeJSStackPop()) + default: + fatalError("Unknown APIResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .failure(let param0): + param0.bridgeJSStackPush() + return Int32(1) + } + } +} + +@_expose(wasm, "bjs_APIResult_static_roundtrip") +@_cdecl("bjs_APIResult_static_roundtrip") +public func _bjs_APIResult_static_roundtrip(_ value: Int32) -> Void { + #if arch(wasm32) + let ret = APIResult.roundtrip(value: APIResult.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Utils_String_static_uppercase") +@_cdecl("bjs_Utils_String_static_uppercase") +public func _bjs_Utils_String_static_uppercase(_ textBytes: Int32, _ textLength: Int32) -> Void { + #if arch(wasm32) + let ret = Utils.String.uppercase(_: String.bridgeJSLiftParameter(textBytes, textLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_init") +@_cdecl("bjs_MathUtils_init") +public func _bjs_MathUtils_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = MathUtils() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_static_subtract") +@_cdecl("bjs_MathUtils_static_subtract") +public func _bjs_MathUtils_static_subtract(_ a: Int32, _ b: Int32) -> Int32 { + #if arch(wasm32) + let ret = MathUtils.subtract(a: Int.bridgeJSLiftParameter(a), b: Int.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_static_add") +@_cdecl("bjs_MathUtils_static_add") +public func _bjs_MathUtils_static_add(_ a: Int32, _ b: Int32) -> Int32 { + #if arch(wasm32) + let ret = MathUtils.add(a: Int.bridgeJSLiftParameter(a), b: Int.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_multiply") +@_cdecl("bjs_MathUtils_multiply") +public func _bjs_MathUtils_multiply(_ _self: UnsafeMutableRawPointer, _ x: Int32, _ y: Int32) -> Int32 { + #if arch(wasm32) + let ret = MathUtils.bridgeJSLiftParameter(_self).multiply(x: Int.bridgeJSLiftParameter(x), y: Int.bridgeJSLiftParameter(y)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_deinit") +@_cdecl("bjs_MathUtils_deinit") +public func _bjs_MathUtils_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension MathUtils: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_MathUtils_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_MathUtils_wrap") +fileprivate func _bjs_MathUtils_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_MathUtils_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.json new file mode 100644 index 000000000..e4ec22855 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.json @@ -0,0 +1,339 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_MathUtils_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_MathUtils_static_subtract", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "subtract", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "int" : { + + } + } + }, + { + "label" : "b", + "name" : "b", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "className" : { + "_0" : "MathUtils" + } + } + }, + { + "abiName" : "bjs_MathUtils_static_add", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "add", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "int" : { + + } + } + }, + { + "label" : "b", + "name" : "b", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "className" : { + "_0" : "MathUtils" + } + } + }, + { + "abiName" : "bjs_MathUtils_multiply", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "multiply", + "parameters" : [ + { + "label" : "x", + "name" : "x", + "type" : { + "int" : { + + } + } + }, + { + "label" : "y", + "name" : "y", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + } + } + ], + "name" : "MathUtils", + "properties" : [ + + ], + "swiftCallName" : "MathUtils" + } + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "scientific" + }, + { + "associatedValues" : [ + + ], + "name" : "basic" + } + ], + "emitStyle" : "const", + "name" : "Calculator", + "staticMethods" : [ + { + "abiName" : "bjs_Calculator_static_square", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "square", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "enumName" : { + "_0" : "Calculator" + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Calculator", + "tsFullPath" : "Calculator" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + } + ], + "emitStyle" : "const", + "name" : "APIResult", + "staticMethods" : [ + { + "abiName" : "bjs_APIResult_static_roundtrip", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "roundtrip", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "staticContext" : { + "enumName" : { + "_0" : "APIResult" + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "APIResult", + "tsFullPath" : "APIResult" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Utils", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utils", + "tsFullPath" : "Utils" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "String", + "namespace" : [ + "Utils" + ], + "staticMethods" : [ + { + "abiName" : "bjs_Utils_String_static_uppercase", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "uppercase", + "namespace" : [ + "Utils", + "String" + ], + "parameters" : [ + { + "label" : "_", + "name" : "text", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "Utils.String" + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utils.String", + "tsFullPath" : "Utils.String" + } + ], + "exposeToGlobal" : false, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.swift new file mode 100644 index 000000000..8ad34d283 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.swift @@ -0,0 +1,160 @@ +extension Calculator: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Calculator { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Calculator { + return Calculator(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .scientific + case 1: + self = .basic + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .scientific: + return 0 + case .basic: + return 1 + } + } +} + +@_expose(wasm, "bjs_Calculator_static_square") +@_cdecl("bjs_Calculator_static_square") +public func _bjs_Calculator_static_square(_ value: Int32) -> Int32 { + #if arch(wasm32) + let ret = Calculator.square(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension APIResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> APIResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(Int.bridgeJSStackPop()) + default: + fatalError("Unknown APIResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .failure(let param0): + param0.bridgeJSStackPush() + return Int32(1) + } + } +} + +@_expose(wasm, "bjs_APIResult_static_roundtrip") +@_cdecl("bjs_APIResult_static_roundtrip") +public func _bjs_APIResult_static_roundtrip(_ value: Int32) -> Void { + #if arch(wasm32) + let ret = APIResult.roundtrip(value: APIResult.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Utils_String_static_uppercase") +@_cdecl("bjs_Utils_String_static_uppercase") +public func _bjs_Utils_String_static_uppercase(_ textBytes: Int32, _ textLength: Int32) -> Void { + #if arch(wasm32) + let ret = Utils.String.uppercase(_: String.bridgeJSLiftParameter(textBytes, textLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_init") +@_cdecl("bjs_MathUtils_init") +public func _bjs_MathUtils_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = MathUtils() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_static_subtract") +@_cdecl("bjs_MathUtils_static_subtract") +public func _bjs_MathUtils_static_subtract(_ a: Int32, _ b: Int32) -> Int32 { + #if arch(wasm32) + let ret = MathUtils.subtract(a: Int.bridgeJSLiftParameter(a), b: Int.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_static_add") +@_cdecl("bjs_MathUtils_static_add") +public func _bjs_MathUtils_static_add(_ a: Int32, _ b: Int32) -> Int32 { + #if arch(wasm32) + let ret = MathUtils.add(a: Int.bridgeJSLiftParameter(a), b: Int.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_multiply") +@_cdecl("bjs_MathUtils_multiply") +public func _bjs_MathUtils_multiply(_ _self: UnsafeMutableRawPointer, _ x: Int32, _ y: Int32) -> Int32 { + #if arch(wasm32) + let ret = MathUtils.bridgeJSLiftParameter(_self).multiply(x: Int.bridgeJSLiftParameter(x), y: Int.bridgeJSLiftParameter(y)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_deinit") +@_cdecl("bjs_MathUtils_deinit") +public func _bjs_MathUtils_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension MathUtils: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_MathUtils_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_MathUtils_wrap") +fileprivate func _bjs_MathUtils_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_MathUtils_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticProperties.Global.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticProperties.Global.json new file mode 100644 index 000000000..bb9e48091 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticProperties.Global.json @@ -0,0 +1,343 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_PropertyClass_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + + ], + "name" : "PropertyClass", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : true, + "name" : "staticConstant", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "staticVariable", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "jsObjectProperty", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "jsObject" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "classVariable", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "computedProperty", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "readOnlyComputed", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "optionalProperty", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "PropertyClass" + } + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "value1" + }, + { + "associatedValues" : [ + + ], + "name" : "value2" + } + ], + "emitStyle" : "const", + "name" : "PropertyEnum", + "staticMethods" : [ + + ], + "staticProperties" : [ + { + "isReadonly" : false, + "isStatic" : true, + "name" : "enumProperty", + "staticContext" : { + "enumName" : { + "_0" : "PropertyEnum" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "enumConstant", + "staticContext" : { + "enumName" : { + "_0" : "PropertyEnum" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "computedEnum", + "staticContext" : { + "enumName" : { + "_0" : "PropertyEnum" + } + }, + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "PropertyEnum", + "tsFullPath" : "PropertyEnum" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "PropertyNamespace", + "staticMethods" : [ + + ], + "staticProperties" : [ + { + "isReadonly" : false, + "isStatic" : true, + "name" : "namespaceProperty", + "namespace" : [ + "PropertyNamespace" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "PropertyNamespace" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "namespaceConstant", + "namespace" : [ + "PropertyNamespace" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "PropertyNamespace" + } + }, + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "PropertyNamespace", + "tsFullPath" : "PropertyNamespace" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Nested", + "namespace" : [ + "PropertyNamespace" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + { + "isReadonly" : false, + "isStatic" : true, + "name" : "nestedProperty", + "namespace" : [ + "PropertyNamespace", + "Nested" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "PropertyNamespace.Nested" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "nestedConstant", + "namespace" : [ + "PropertyNamespace", + "Nested" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "PropertyNamespace.Nested" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "nestedDouble", + "namespace" : [ + "PropertyNamespace", + "Nested" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "PropertyNamespace.Nested" + } + }, + "type" : { + "double" : { + + } + } + } + ], + "swiftCallName" : "PropertyNamespace.Nested", + "tsFullPath" : "PropertyNamespace.Nested" + } + ], + "exposeToGlobal" : true, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticProperties.Global.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticProperties.Global.swift new file mode 100644 index 000000000..6510fd89f --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticProperties.Global.swift @@ -0,0 +1,335 @@ +extension PropertyEnum: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> PropertyEnum { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> PropertyEnum { + return PropertyEnum(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .value1 + case 1: + self = .value2 + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .value1: + return 0 + case .value2: + return 1 + } + } +} + +@_expose(wasm, "bjs_PropertyEnum_static_enumProperty_get") +@_cdecl("bjs_PropertyEnum_static_enumProperty_get") +public func _bjs_PropertyEnum_static_enumProperty_get() -> Void { + #if arch(wasm32) + let ret = PropertyEnum.enumProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyEnum_static_enumProperty_set") +@_cdecl("bjs_PropertyEnum_static_enumProperty_set") +public func _bjs_PropertyEnum_static_enumProperty_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyEnum.enumProperty = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyEnum_static_enumConstant_get") +@_cdecl("bjs_PropertyEnum_static_enumConstant_get") +public func _bjs_PropertyEnum_static_enumConstant_get() -> Int32 { + #if arch(wasm32) + let ret = PropertyEnum.enumConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyEnum_static_computedEnum_get") +@_cdecl("bjs_PropertyEnum_static_computedEnum_get") +public func _bjs_PropertyEnum_static_computedEnum_get() -> Void { + #if arch(wasm32) + let ret = PropertyEnum.computedEnum + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyEnum_static_computedEnum_set") +@_cdecl("bjs_PropertyEnum_static_computedEnum_set") +public func _bjs_PropertyEnum_static_computedEnum_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyEnum.computedEnum = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_static_namespaceProperty_get") +@_cdecl("bjs_PropertyNamespace_static_namespaceProperty_get") +public func _bjs_PropertyNamespace_static_namespaceProperty_get() -> Void { + #if arch(wasm32) + let ret = PropertyNamespace.namespaceProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_static_namespaceProperty_set") +@_cdecl("bjs_PropertyNamespace_static_namespaceProperty_set") +public func _bjs_PropertyNamespace_static_namespaceProperty_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyNamespace.namespaceProperty = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_static_namespaceConstant_get") +@_cdecl("bjs_PropertyNamespace_static_namespaceConstant_get") +public func _bjs_PropertyNamespace_static_namespaceConstant_get() -> Void { + #if arch(wasm32) + let ret = PropertyNamespace.namespaceConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_Nested_static_nestedProperty_get") +@_cdecl("bjs_PropertyNamespace_Nested_static_nestedProperty_get") +public func _bjs_PropertyNamespace_Nested_static_nestedProperty_get() -> Int32 { + #if arch(wasm32) + let ret = PropertyNamespace.Nested.nestedProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_Nested_static_nestedProperty_set") +@_cdecl("bjs_PropertyNamespace_Nested_static_nestedProperty_set") +public func _bjs_PropertyNamespace_Nested_static_nestedProperty_set(_ value: Int32) -> Void { + #if arch(wasm32) + PropertyNamespace.Nested.nestedProperty = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_Nested_static_nestedConstant_get") +@_cdecl("bjs_PropertyNamespace_Nested_static_nestedConstant_get") +public func _bjs_PropertyNamespace_Nested_static_nestedConstant_get() -> Void { + #if arch(wasm32) + let ret = PropertyNamespace.Nested.nestedConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_Nested_static_nestedDouble_get") +@_cdecl("bjs_PropertyNamespace_Nested_static_nestedDouble_get") +public func _bjs_PropertyNamespace_Nested_static_nestedDouble_get() -> Float64 { + #if arch(wasm32) + let ret = PropertyNamespace.Nested.nestedDouble + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_Nested_static_nestedDouble_set") +@_cdecl("bjs_PropertyNamespace_Nested_static_nestedDouble_set") +public func _bjs_PropertyNamespace_Nested_static_nestedDouble_set(_ value: Float64) -> Void { + #if arch(wasm32) + PropertyNamespace.Nested.nestedDouble = Double.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_init") +@_cdecl("bjs_PropertyClass_init") +public func _bjs_PropertyClass_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = PropertyClass() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_staticConstant_get") +@_cdecl("bjs_PropertyClass_static_staticConstant_get") +public func _bjs_PropertyClass_static_staticConstant_get() -> Void { + #if arch(wasm32) + let ret = PropertyClass.staticConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_staticVariable_get") +@_cdecl("bjs_PropertyClass_static_staticVariable_get") +public func _bjs_PropertyClass_static_staticVariable_get() -> Int32 { + #if arch(wasm32) + let ret = PropertyClass.staticVariable + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_staticVariable_set") +@_cdecl("bjs_PropertyClass_static_staticVariable_set") +public func _bjs_PropertyClass_static_staticVariable_set(_ value: Int32) -> Void { + #if arch(wasm32) + PropertyClass.staticVariable = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_jsObjectProperty_get") +@_cdecl("bjs_PropertyClass_static_jsObjectProperty_get") +public func _bjs_PropertyClass_static_jsObjectProperty_get() -> Int32 { + #if arch(wasm32) + let ret = PropertyClass.jsObjectProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_jsObjectProperty_set") +@_cdecl("bjs_PropertyClass_static_jsObjectProperty_set") +public func _bjs_PropertyClass_static_jsObjectProperty_set(_ value: Int32) -> Void { + #if arch(wasm32) + PropertyClass.jsObjectProperty = JSObject.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_classVariable_get") +@_cdecl("bjs_PropertyClass_static_classVariable_get") +public func _bjs_PropertyClass_static_classVariable_get() -> Void { + #if arch(wasm32) + let ret = PropertyClass.classVariable + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_classVariable_set") +@_cdecl("bjs_PropertyClass_static_classVariable_set") +public func _bjs_PropertyClass_static_classVariable_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyClass.classVariable = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_computedProperty_get") +@_cdecl("bjs_PropertyClass_static_computedProperty_get") +public func _bjs_PropertyClass_static_computedProperty_get() -> Void { + #if arch(wasm32) + let ret = PropertyClass.computedProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_computedProperty_set") +@_cdecl("bjs_PropertyClass_static_computedProperty_set") +public func _bjs_PropertyClass_static_computedProperty_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyClass.computedProperty = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_readOnlyComputed_get") +@_cdecl("bjs_PropertyClass_static_readOnlyComputed_get") +public func _bjs_PropertyClass_static_readOnlyComputed_get() -> Int32 { + #if arch(wasm32) + let ret = PropertyClass.readOnlyComputed + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_optionalProperty_get") +@_cdecl("bjs_PropertyClass_static_optionalProperty_get") +public func _bjs_PropertyClass_static_optionalProperty_get() -> Void { + #if arch(wasm32) + let ret = PropertyClass.optionalProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_optionalProperty_set") +@_cdecl("bjs_PropertyClass_static_optionalProperty_set") +public func _bjs_PropertyClass_static_optionalProperty_set(_ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyClass.optionalProperty = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_deinit") +@_cdecl("bjs_PropertyClass_deinit") +public func _bjs_PropertyClass_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension PropertyClass: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_PropertyClass_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_PropertyClass_wrap") +fileprivate func _bjs_PropertyClass_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_PropertyClass_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticProperties.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticProperties.json new file mode 100644 index 000000000..d385e3887 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticProperties.json @@ -0,0 +1,343 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_PropertyClass_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + + ], + "name" : "PropertyClass", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : true, + "name" : "staticConstant", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "staticVariable", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "jsObjectProperty", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "jsObject" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "classVariable", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "computedProperty", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "readOnlyComputed", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "optionalProperty", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "PropertyClass" + } + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "value1" + }, + { + "associatedValues" : [ + + ], + "name" : "value2" + } + ], + "emitStyle" : "const", + "name" : "PropertyEnum", + "staticMethods" : [ + + ], + "staticProperties" : [ + { + "isReadonly" : false, + "isStatic" : true, + "name" : "enumProperty", + "staticContext" : { + "enumName" : { + "_0" : "PropertyEnum" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "enumConstant", + "staticContext" : { + "enumName" : { + "_0" : "PropertyEnum" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "computedEnum", + "staticContext" : { + "enumName" : { + "_0" : "PropertyEnum" + } + }, + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "PropertyEnum", + "tsFullPath" : "PropertyEnum" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "PropertyNamespace", + "staticMethods" : [ + + ], + "staticProperties" : [ + { + "isReadonly" : false, + "isStatic" : true, + "name" : "namespaceProperty", + "namespace" : [ + "PropertyNamespace" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "PropertyNamespace" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "namespaceConstant", + "namespace" : [ + "PropertyNamespace" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "PropertyNamespace" + } + }, + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "PropertyNamespace", + "tsFullPath" : "PropertyNamespace" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Nested", + "namespace" : [ + "PropertyNamespace" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + { + "isReadonly" : false, + "isStatic" : true, + "name" : "nestedProperty", + "namespace" : [ + "PropertyNamespace", + "Nested" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "PropertyNamespace.Nested" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "nestedConstant", + "namespace" : [ + "PropertyNamespace", + "Nested" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "PropertyNamespace.Nested" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "nestedDouble", + "namespace" : [ + "PropertyNamespace", + "Nested" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "PropertyNamespace.Nested" + } + }, + "type" : { + "double" : { + + } + } + } + ], + "swiftCallName" : "PropertyNamespace.Nested", + "tsFullPath" : "PropertyNamespace.Nested" + } + ], + "exposeToGlobal" : false, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticProperties.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticProperties.swift new file mode 100644 index 000000000..6510fd89f --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticProperties.swift @@ -0,0 +1,335 @@ +extension PropertyEnum: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> PropertyEnum { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> PropertyEnum { + return PropertyEnum(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .value1 + case 1: + self = .value2 + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .value1: + return 0 + case .value2: + return 1 + } + } +} + +@_expose(wasm, "bjs_PropertyEnum_static_enumProperty_get") +@_cdecl("bjs_PropertyEnum_static_enumProperty_get") +public func _bjs_PropertyEnum_static_enumProperty_get() -> Void { + #if arch(wasm32) + let ret = PropertyEnum.enumProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyEnum_static_enumProperty_set") +@_cdecl("bjs_PropertyEnum_static_enumProperty_set") +public func _bjs_PropertyEnum_static_enumProperty_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyEnum.enumProperty = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyEnum_static_enumConstant_get") +@_cdecl("bjs_PropertyEnum_static_enumConstant_get") +public func _bjs_PropertyEnum_static_enumConstant_get() -> Int32 { + #if arch(wasm32) + let ret = PropertyEnum.enumConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyEnum_static_computedEnum_get") +@_cdecl("bjs_PropertyEnum_static_computedEnum_get") +public func _bjs_PropertyEnum_static_computedEnum_get() -> Void { + #if arch(wasm32) + let ret = PropertyEnum.computedEnum + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyEnum_static_computedEnum_set") +@_cdecl("bjs_PropertyEnum_static_computedEnum_set") +public func _bjs_PropertyEnum_static_computedEnum_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyEnum.computedEnum = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_static_namespaceProperty_get") +@_cdecl("bjs_PropertyNamespace_static_namespaceProperty_get") +public func _bjs_PropertyNamespace_static_namespaceProperty_get() -> Void { + #if arch(wasm32) + let ret = PropertyNamespace.namespaceProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_static_namespaceProperty_set") +@_cdecl("bjs_PropertyNamespace_static_namespaceProperty_set") +public func _bjs_PropertyNamespace_static_namespaceProperty_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyNamespace.namespaceProperty = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_static_namespaceConstant_get") +@_cdecl("bjs_PropertyNamespace_static_namespaceConstant_get") +public func _bjs_PropertyNamespace_static_namespaceConstant_get() -> Void { + #if arch(wasm32) + let ret = PropertyNamespace.namespaceConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_Nested_static_nestedProperty_get") +@_cdecl("bjs_PropertyNamespace_Nested_static_nestedProperty_get") +public func _bjs_PropertyNamespace_Nested_static_nestedProperty_get() -> Int32 { + #if arch(wasm32) + let ret = PropertyNamespace.Nested.nestedProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_Nested_static_nestedProperty_set") +@_cdecl("bjs_PropertyNamespace_Nested_static_nestedProperty_set") +public func _bjs_PropertyNamespace_Nested_static_nestedProperty_set(_ value: Int32) -> Void { + #if arch(wasm32) + PropertyNamespace.Nested.nestedProperty = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_Nested_static_nestedConstant_get") +@_cdecl("bjs_PropertyNamespace_Nested_static_nestedConstant_get") +public func _bjs_PropertyNamespace_Nested_static_nestedConstant_get() -> Void { + #if arch(wasm32) + let ret = PropertyNamespace.Nested.nestedConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_Nested_static_nestedDouble_get") +@_cdecl("bjs_PropertyNamespace_Nested_static_nestedDouble_get") +public func _bjs_PropertyNamespace_Nested_static_nestedDouble_get() -> Float64 { + #if arch(wasm32) + let ret = PropertyNamespace.Nested.nestedDouble + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_Nested_static_nestedDouble_set") +@_cdecl("bjs_PropertyNamespace_Nested_static_nestedDouble_set") +public func _bjs_PropertyNamespace_Nested_static_nestedDouble_set(_ value: Float64) -> Void { + #if arch(wasm32) + PropertyNamespace.Nested.nestedDouble = Double.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_init") +@_cdecl("bjs_PropertyClass_init") +public func _bjs_PropertyClass_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = PropertyClass() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_staticConstant_get") +@_cdecl("bjs_PropertyClass_static_staticConstant_get") +public func _bjs_PropertyClass_static_staticConstant_get() -> Void { + #if arch(wasm32) + let ret = PropertyClass.staticConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_staticVariable_get") +@_cdecl("bjs_PropertyClass_static_staticVariable_get") +public func _bjs_PropertyClass_static_staticVariable_get() -> Int32 { + #if arch(wasm32) + let ret = PropertyClass.staticVariable + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_staticVariable_set") +@_cdecl("bjs_PropertyClass_static_staticVariable_set") +public func _bjs_PropertyClass_static_staticVariable_set(_ value: Int32) -> Void { + #if arch(wasm32) + PropertyClass.staticVariable = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_jsObjectProperty_get") +@_cdecl("bjs_PropertyClass_static_jsObjectProperty_get") +public func _bjs_PropertyClass_static_jsObjectProperty_get() -> Int32 { + #if arch(wasm32) + let ret = PropertyClass.jsObjectProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_jsObjectProperty_set") +@_cdecl("bjs_PropertyClass_static_jsObjectProperty_set") +public func _bjs_PropertyClass_static_jsObjectProperty_set(_ value: Int32) -> Void { + #if arch(wasm32) + PropertyClass.jsObjectProperty = JSObject.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_classVariable_get") +@_cdecl("bjs_PropertyClass_static_classVariable_get") +public func _bjs_PropertyClass_static_classVariable_get() -> Void { + #if arch(wasm32) + let ret = PropertyClass.classVariable + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_classVariable_set") +@_cdecl("bjs_PropertyClass_static_classVariable_set") +public func _bjs_PropertyClass_static_classVariable_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyClass.classVariable = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_computedProperty_get") +@_cdecl("bjs_PropertyClass_static_computedProperty_get") +public func _bjs_PropertyClass_static_computedProperty_get() -> Void { + #if arch(wasm32) + let ret = PropertyClass.computedProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_computedProperty_set") +@_cdecl("bjs_PropertyClass_static_computedProperty_set") +public func _bjs_PropertyClass_static_computedProperty_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyClass.computedProperty = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_readOnlyComputed_get") +@_cdecl("bjs_PropertyClass_static_readOnlyComputed_get") +public func _bjs_PropertyClass_static_readOnlyComputed_get() -> Int32 { + #if arch(wasm32) + let ret = PropertyClass.readOnlyComputed + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_optionalProperty_get") +@_cdecl("bjs_PropertyClass_static_optionalProperty_get") +public func _bjs_PropertyClass_static_optionalProperty_get() -> Void { + #if arch(wasm32) + let ret = PropertyClass.optionalProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_optionalProperty_set") +@_cdecl("bjs_PropertyClass_static_optionalProperty_set") +public func _bjs_PropertyClass_static_optionalProperty_set(_ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyClass.optionalProperty = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_deinit") +@_cdecl("bjs_PropertyClass_deinit") +public func _bjs_PropertyClass_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension PropertyClass: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_PropertyClass_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_PropertyClass_wrap") +fileprivate func _bjs_PropertyClass_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_PropertyClass_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringParameter.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringParameter.json new file mode 100644 index 000000000..b0aa8c35b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringParameter.json @@ -0,0 +1,125 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_checkString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "checkString", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_roundtripString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripString", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "checkString", + "parameters" : [ + { + "name" : "a", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "checkStringWithLength", + "parameters" : [ + { + "name" : "a", + "type" : { + "string" : { + + } + } + }, + { + "name" : "b", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "types" : [ + + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringParameter.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringParameter.swift new file mode 100644 index 000000000..e9e3c2d89 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringParameter.swift @@ -0,0 +1,55 @@ +@_expose(wasm, "bjs_checkString") +@_cdecl("bjs_checkString") +public func _bjs_checkString(_ aBytes: Int32, _ aLength: Int32) -> Void { + #if arch(wasm32) + checkString(a: String.bridgeJSLiftParameter(aBytes, aLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripString") +@_cdecl("bjs_roundtripString") +public func _bjs_roundtripString(_ aBytes: Int32, _ aLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundtripString(a: String.bridgeJSLiftParameter(aBytes, aLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_checkString") +fileprivate func bjs_checkString(_ a: Int32) -> Void +#else +fileprivate func bjs_checkString(_ a: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$checkString(_ a: String) throws(JSException) -> Void { + let aValue = a.bridgeJSLowerParameter() + bjs_checkString(aValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_checkStringWithLength") +fileprivate func bjs_checkStringWithLength(_ a: Int32, _ b: Float64) -> Void +#else +fileprivate func bjs_checkStringWithLength(_ a: Int32, _ b: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$checkStringWithLength(_ a: String, _ b: Double) throws(JSException) -> Void { + let aValue = a.bridgeJSLowerParameter() + let bValue = b.bridgeJSLowerParameter() + bjs_checkStringWithLength(aValue, bValue) + if let error = _swift_js_take_exception() { + throw error + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringReturn.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringReturn.json new file mode 100644 index 000000000..3f9271592 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringReturn.json @@ -0,0 +1,59 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_checkString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "checkString", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "checkString", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "types" : [ + + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringReturn.swift new file mode 100644 index 000000000..9de24ef73 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringReturn.swift @@ -0,0 +1,27 @@ +@_expose(wasm, "bjs_checkString") +@_cdecl("bjs_checkString") +public func _bjs_checkString() -> Void { + #if arch(wasm32) + let ret = checkString() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_checkString") +fileprivate func bjs_checkString() -> Int32 +#else +fileprivate func bjs_checkString() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$checkString() throws(JSException) -> String { + let ret = bjs_checkString() + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.json new file mode 100644 index 000000000..7cebdd5e6 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.json @@ -0,0 +1,202 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_Greeter_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_Greeter_greet", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "greet", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_Greeter_changeName", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "changeName", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "Greeter", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "Greeter" + }, + { + "explicitAccessControl" : "public", + "methods" : [ + + ], + "name" : "PublicGreeter", + "properties" : [ + + ], + "swiftCallName" : "PublicGreeter" + }, + { + "explicitAccessControl" : "package", + "methods" : [ + + ], + "name" : "PackageGreeter", + "properties" : [ + + ], + "swiftCallName" : "PackageGreeter" + } + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_takeGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeGreeter", + "parameters" : [ + { + "label" : "greeter", + "name" : "greeter", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "jsRoundTripGreeter", + "parameters" : [ + { + "name" : "greeter", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "name" : "jsRoundTripOptionalGreeter", + "parameters" : [ + { + "name" : "greeter", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ], + "types" : [ + + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.swift new file mode 100644 index 000000000..ca82b87c4 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.swift @@ -0,0 +1,173 @@ +@_expose(wasm, "bjs_takeGreeter") +@_cdecl("bjs_takeGreeter") +public func _bjs_takeGreeter(_ greeter: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + takeGreeter(greeter: Greeter.bridgeJSLiftParameter(greeter)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_init") +@_cdecl("bjs_Greeter_init") +public func _bjs_Greeter_init(_ nameBytes: Int32, _ nameLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Greeter(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_greet") +@_cdecl("bjs_Greeter_greet") +public func _bjs_Greeter_greet(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Greeter.bridgeJSLiftParameter(_self).greet() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_changeName") +@_cdecl("bjs_Greeter_changeName") +public func _bjs_Greeter_changeName(_ _self: UnsafeMutableRawPointer, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + Greeter.bridgeJSLiftParameter(_self).changeName(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_name_get") +@_cdecl("bjs_Greeter_name_get") +public func _bjs_Greeter_name_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Greeter.bridgeJSLiftParameter(_self).name + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_name_set") +@_cdecl("bjs_Greeter_name_set") +public func _bjs_Greeter_name_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + Greeter.bridgeJSLiftParameter(_self).name = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_deinit") +@_cdecl("bjs_Greeter_deinit") +public func _bjs_Greeter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Greeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Greeter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Greeter_wrap") +fileprivate func _bjs_Greeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Greeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_PublicGreeter_deinit") +@_cdecl("bjs_PublicGreeter_deinit") +public func _bjs_PublicGreeter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension PublicGreeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + public var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_PublicGreeter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_PublicGreeter_wrap") +fileprivate func _bjs_PublicGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_PublicGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_PackageGreeter_deinit") +@_cdecl("bjs_PackageGreeter_deinit") +public func _bjs_PackageGreeter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension PackageGreeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + package var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_PackageGreeter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_PackageGreeter_wrap") +fileprivate func _bjs_PackageGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_PackageGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_jsRoundTripGreeter") +fileprivate func bjs_jsRoundTripGreeter(_ greeter: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer +#else +fileprivate func bjs_jsRoundTripGreeter(_ greeter: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripGreeter(_ greeter: Greeter) throws(JSException) -> Greeter { + let greeterPointer = greeter.bridgeJSLowerParameter() + let ret = bjs_jsRoundTripGreeter(greeterPointer) + if let error = _swift_js_take_exception() { + throw error + } + return Greeter.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_jsRoundTripOptionalGreeter") +fileprivate func bjs_jsRoundTripOptionalGreeter(_ greeterIsSome: Int32, _ greeterPointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer +#else +fileprivate func bjs_jsRoundTripOptionalGreeter(_ greeterIsSome: Int32, _ greeterPointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripOptionalGreeter(_ greeter: Optional) throws(JSException) -> Optional { + let (greeterIsSome, greeterPointer) = greeter.bridgeJSLowerParameter() + let ret = bjs_jsRoundTripOptionalGreeter(greeterIsSome, greeterPointer) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturn(ret) +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.json new file mode 100644 index 000000000..11c6cb893 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.json @@ -0,0 +1,1809 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_Person_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ] + }, + "explicitAccessControl" : "public", + "methods" : [ + + ], + "name" : "Person", + "properties" : [ + + ], + "swiftCallName" : "Person" + }, + { + "constructor" : { + "abiName" : "bjs_TestProcessor_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "transform", + "name" : "transform", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSS_SS", + "moduleName" : "TestModule", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "TestProcessor", + "properties" : [ + + ], + "swiftCallName" : "TestProcessor" + } + ], + "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" : "light", + "rawValue" : "light" + }, + { + "associatedValues" : [ + + ], + "name" : "dark", + "rawValue" : "dark" + }, + { + "associatedValues" : [ + + ], + "name" : "auto", + "rawValue" : "auto" + } + ], + "emitStyle" : "const", + "name" : "Theme", + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Theme", + "tsFullPath" : "Theme" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "ok", + "rawValue" : "200" + }, + { + "associatedValues" : [ + + ], + "name" : "notFound", + "rawValue" : "404" + }, + { + "associatedValues" : [ + + ], + "name" : "serverError", + "rawValue" : "500" + }, + { + "associatedValues" : [ + + ], + "name" : "unknown", + "rawValue" : "-1" + } + ], + "emitStyle" : "const", + "name" : "HttpStatus", + "rawType" : "Int", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "HttpStatus", + "tsFullPath" : "HttpStatus" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "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" : [ + + ], + "name" : "info" + } + ], + "emitStyle" : "const", + "name" : "APIResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "APIResult", + "tsFullPath" : "APIResult" + } + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_roundtripString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripString", + "parameters" : [ + { + "label" : "_", + "name" : "stringClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSS_SS", + "moduleName" : "TestModule", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSS_SS", + "moduleName" : "TestModule", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripInt", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripInt", + "parameters" : [ + { + "label" : "_", + "name" : "intClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSi_Si", + "moduleName" : "TestModule", + "parameters" : [ + { + "int" : { + + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSi_Si", + "moduleName" : "TestModule", + "parameters" : [ + { + "int" : { + + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripBool", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripBool", + "parameters" : [ + { + "label" : "_", + "name" : "boolClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSb_Sb", + "moduleName" : "TestModule", + "parameters" : [ + { + "bool" : { + + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSb_Sb", + "moduleName" : "TestModule", + "parameters" : [ + { + "bool" : { + + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripFloat", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripFloat", + "parameters" : [ + { + "label" : "_", + "name" : "floatClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSf_Sf", + "moduleName" : "TestModule", + "parameters" : [ + { + "float" : { + + } + } + ], + "returnType" : { + "float" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSf_Sf", + "moduleName" : "TestModule", + "parameters" : [ + { + "float" : { + + } + } + ], + "returnType" : { + "float" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripDouble", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripDouble", + "parameters" : [ + { + "label" : "_", + "name" : "doubleClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSd_Sd", + "moduleName" : "TestModule", + "parameters" : [ + { + "double" : { + + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSd_Sd", + "moduleName" : "TestModule", + "parameters" : [ + { + "double" : { + + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalString", + "parameters" : [ + { + "label" : "_", + "name" : "stringClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSqSS_SqSS", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSqSS_SqSS", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalInt", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalInt", + "parameters" : [ + { + "label" : "_", + "name" : "intClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSqSi_SqSi", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSqSi_SqSi", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalBool", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalBool", + "parameters" : [ + { + "label" : "_", + "name" : "boolClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSqSb_SqSb", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSqSb_SqSb", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalFloat", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalFloat", + "parameters" : [ + { + "label" : "_", + "name" : "floatClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSqSf_SqSf", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "float" : { + + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "float" : { + + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSqSf_SqSf", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "float" : { + + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "float" : { + + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalDouble", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalDouble", + "parameters" : [ + { + "label" : "_", + "name" : "doubleClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSqSd_SqSd", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSqSd_SqSd", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripPerson", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripPerson", + "parameters" : [ + { + "label" : "_", + "name" : "personClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule6PersonC_6PersonC", + "moduleName" : "TestModule", + "parameters" : [ + { + "swiftHeapObject" : { + "_0" : "Person" + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Person" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule6PersonC_6PersonC", + "moduleName" : "TestModule", + "parameters" : [ + { + "swiftHeapObject" : { + "_0" : "Person" + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Person" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalPerson", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalPerson", + "parameters" : [ + { + "label" : "_", + "name" : "personClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq6PersonC_Sq6PersonC", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Person" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Person" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq6PersonC_Sq6PersonC", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Person" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Person" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripDirection", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule9DirectionO_9DirectionO", + "moduleName" : "TestModule", + "parameters" : [ + { + "caseEnum" : { + "_0" : "Direction" + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "Direction" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule9DirectionO_9DirectionO", + "moduleName" : "TestModule", + "parameters" : [ + { + "caseEnum" : { + "_0" : "Direction" + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "Direction" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripTheme", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule5ThemeO_5ThemeO", + "moduleName" : "TestModule", + "parameters" : [ + { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule5ThemeO_5ThemeO", + "moduleName" : "TestModule", + "parameters" : [ + { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripHttpStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripHttpStatus", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule10HttpStatusO_10HttpStatusO", + "moduleName" : "TestModule", + "parameters" : [ + { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule10HttpStatusO_10HttpStatusO", + "moduleName" : "TestModule", + "parameters" : [ + { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripAPIResult", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule9APIResultO_9APIResultO", + "moduleName" : "TestModule", + "parameters" : [ + { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule9APIResultO_9APIResultO", + "moduleName" : "TestModule", + "parameters" : [ + { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalDirection", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq9DirectionO_Sq9DirectionO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq9DirectionO_Sq9DirectionO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalTheme", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq5ThemeO_Sq5ThemeO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq5ThemeO_Sq5ThemeO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalHttpStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalHttpStatus", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq10HttpStatusO_Sq10HttpStatusO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq10HttpStatusO_Sq10HttpStatusO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalAPIResult", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq9APIResultO_Sq9APIResultO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq9APIResultO_Sq9APIResultO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalDirection", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq9DirectionO_Sq9DirectionO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq9DirectionO_Sq9DirectionO", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift new file mode 100644 index 000000000..925ab5937 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift @@ -0,0 +1,1534 @@ +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule10HttpStatusO_10HttpStatusO") +fileprivate func invoke_js_callback_TestModule_10TestModule10HttpStatusO_10HttpStatusO(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_TestModule_10TestModule10HttpStatusO_10HttpStatusO(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO") +fileprivate func make_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModule10HttpStatusO_10HttpStatusO { + static func bridgeJSLift(_ callbackId: Int32) -> (HttpStatus) -> HttpStatus { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModule10HttpStatusO_10HttpStatusO(callbackValue, param0Value) + return HttpStatus.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (HttpStatus) -> HttpStatus { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (HttpStatus) -> HttpStatus) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO") +@_cdecl("invoke_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO") +public func _invoke_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(HttpStatus) -> HttpStatus>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(HttpStatus.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO") +fileprivate func invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO") +fileprivate func make_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModule5ThemeO_5ThemeO { + static func bridgeJSLift(_ callbackId: Int32) -> (Theme) -> Theme { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO(callbackValue, param0Value) + return Theme.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Theme) -> Theme { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Theme) -> Theme) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO") +@_cdecl("invoke_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO") +public func _invoke_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Theme) -> Theme>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Theme.bridgeJSLiftParameter(param0Bytes, param0Length)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule6PersonC_6PersonC") +fileprivate func invoke_js_callback_TestModule_10TestModule6PersonC_6PersonC(_ callback: Int32, _ param0: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer +#else +fileprivate func invoke_js_callback_TestModule_10TestModule6PersonC_6PersonC(_ callback: Int32, _ param0: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule6PersonC_6PersonC") +fileprivate func make_swift_closure_TestModule_10TestModule6PersonC_6PersonC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModule6PersonC_6PersonC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModule6PersonC_6PersonC { + static func bridgeJSLift(_ callbackId: Int32) -> (Person) -> Person { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Pointer = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModule6PersonC_6PersonC(callbackValue, param0Pointer) + return Person.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Person) -> Person { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Person) -> Person) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModule6PersonC_6PersonC, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule6PersonC_6PersonC") +@_cdecl("invoke_swift_closure_TestModule_10TestModule6PersonC_6PersonC") +public func _invoke_swift_closure_TestModule_10TestModule6PersonC_6PersonC(_ boxPtr: UnsafeMutableRawPointer, _ param0: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Person) -> Person>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Person.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule9APIResultO_9APIResultO") +fileprivate func invoke_js_callback_TestModule_10TestModule9APIResultO_9APIResultO(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_TestModule_10TestModule9APIResultO_9APIResultO(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO") +fileprivate func make_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModule9APIResultO_9APIResultO { + static func bridgeJSLift(_ callbackId: Int32) -> (APIResult) -> APIResult { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0CaseId = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModule9APIResultO_9APIResultO(callbackValue, param0CaseId) + return APIResult.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (APIResult) -> APIResult { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (APIResult) -> APIResult) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO") +@_cdecl("invoke_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO") +public func _invoke_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(APIResult) -> APIResult>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(APIResult.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule9DirectionO_9DirectionO") +fileprivate func invoke_js_callback_TestModule_10TestModule9DirectionO_9DirectionO(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_TestModule_10TestModule9DirectionO_9DirectionO(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO") +fileprivate func make_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModule9DirectionO_9DirectionO { + static func bridgeJSLift(_ callbackId: Int32) -> (Direction) -> Direction { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModule9DirectionO_9DirectionO(callbackValue, param0Value) + return Direction.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Direction) -> Direction { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Direction) -> Direction) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO") +@_cdecl("invoke_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO") +public func _invoke_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Direction) -> Direction>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Direction.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSS_SS") +fileprivate func invoke_js_callback_TestModule_10TestModuleSS_SS(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSS_SS(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSS_SS") +fileprivate func make_swift_closure_TestModule_10TestModuleSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSS_SS { + static func bridgeJSLift(_ callbackId: Int32) -> (String) -> String { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModuleSS_SS(callbackValue, param0Value) + return String.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (String) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (String) -> String) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSS_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSS_SS") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSS_SS") +public func _invoke_swift_closure_TestModule_10TestModuleSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(String) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(String.bridgeJSLiftParameter(param0Bytes, param0Length)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSb_Sb") +fileprivate func invoke_js_callback_TestModule_10TestModuleSb_Sb(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSb_Sb(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSb_Sb") +fileprivate func make_swift_closure_TestModule_10TestModuleSb_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSb_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSb_Sb { + static func bridgeJSLift(_ callbackId: Int32) -> (Bool) -> Bool { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModuleSb_Sb(callbackValue, param0Value) + return Bool.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Bool) -> Bool { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Bool) -> Bool) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSb_Sb, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSb_Sb") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSb_Sb") +public func _invoke_swift_closure_TestModule_10TestModuleSb_Sb(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Bool) -> Bool>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Bool.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSd_Sd") +fileprivate func invoke_js_callback_TestModule_10TestModuleSd_Sd(_ callback: Int32, _ param0: Float64) -> Float64 +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSd_Sd(_ callback: Int32, _ param0: Float64) -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSd_Sd") +fileprivate func make_swift_closure_TestModule_10TestModuleSd_Sd(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSd_Sd(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSd_Sd { + static func bridgeJSLift(_ callbackId: Int32) -> (Double) -> Double { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModuleSd_Sd(callbackValue, param0Value) + return Double.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Double) -> Double { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Double) -> Double) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSd_Sd, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSd_Sd") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSd_Sd") +public func _invoke_swift_closure_TestModule_10TestModuleSd_Sd(_ boxPtr: UnsafeMutableRawPointer, _ param0: Float64) -> Float64 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Double) -> Double>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Double.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSf_Sf") +fileprivate func invoke_js_callback_TestModule_10TestModuleSf_Sf(_ callback: Int32, _ param0: Float32) -> Float32 +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSf_Sf(_ callback: Int32, _ param0: Float32) -> Float32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSf_Sf") +fileprivate func make_swift_closure_TestModule_10TestModuleSf_Sf(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSf_Sf(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSf_Sf { + static func bridgeJSLift(_ callbackId: Int32) -> (Float) -> Float { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModuleSf_Sf(callbackValue, param0Value) + return Float.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Float) -> Float { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Float) -> Float) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSf_Sf, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSf_Sf") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSf_Sf") +public func _invoke_swift_closure_TestModule_10TestModuleSf_Sf(_ boxPtr: UnsafeMutableRawPointer, _ param0: Float32) -> Float32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Float) -> Float>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Float.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSi_Si") +fileprivate func invoke_js_callback_TestModule_10TestModuleSi_Si(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSi_Si(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSi_Si") +fileprivate func make_swift_closure_TestModule_10TestModuleSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSi_Si { + static func bridgeJSLift(_ callbackId: Int32) -> (Int) -> Int { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModuleSi_Si(callbackValue, param0Value) + return Int.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Int) -> Int { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Int) -> Int) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSi_Si, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSi_Si") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSi_Si") +public func _invoke_swift_closure_TestModule_10TestModuleSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Int) -> Int>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Int.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO") +fileprivate func invoke_js_callback_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Void +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO") +fileprivate func make_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSq10HttpStatusO_Sq10HttpStatusO { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + invoke_js_callback_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(callbackValue, param0IsSome, param0Value) + return Optional.bridgeJSLiftReturnFromSideChannel() + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO") +public func _invoke_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO") +fileprivate func invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Void +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO") +fileprivate func make_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSq5ThemeO_Sq5ThemeO { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(callbackValue, param0IsSome, param0Value) + return Optional.bridgeJSLiftReturnFromSideChannel() + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO") +public func _invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Bytes, param0Length)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC") +fileprivate func invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC(_ callback: Int32, _ param0IsSome: Int32, _ param0Pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC(_ callback: Int32, _ param0IsSome: Int32, _ param0Pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC") +fileprivate func make_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSq6PersonC_Sq6PersonC { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Pointer) = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC(callbackValue, param0IsSome, param0Pointer) + return Optional.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC") +public func _invoke_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO") +fileprivate func invoke_js_callback_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(_ callback: Int32, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(_ callback: Int32, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO") +fileprivate func make_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSq9APIResultO_Sq9APIResultO { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0CaseId) = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(callbackValue, param0IsSome, param0CaseId) + return Optional.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO") +public func _invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0CaseId)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO") +fileprivate func invoke_js_callback_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO") +fileprivate func make_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSq9DirectionO_Sq9DirectionO { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(callbackValue, param0IsSome, param0Value) + return Optional.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO") +public func _invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSqSS_SqSS") +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSS_SqSS(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Void +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSS_SqSS(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSqSS_SqSS") +fileprivate func make_swift_closure_TestModule_10TestModuleSqSS_SqSS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSqSS_SqSS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSqSS_SqSS { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + invoke_js_callback_TestModule_10TestModuleSqSS_SqSS(callbackValue, param0IsSome, param0Value) + return Optional.bridgeJSLiftReturnFromSideChannel() + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSqSS_SqSS, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSqSS_SqSS") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSqSS_SqSS") +public func _invoke_swift_closure_TestModule_10TestModuleSqSS_SqSS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Bytes, param0Length)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSqSb_SqSb") +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSb_SqSb(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSb_SqSb(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSqSb_SqSb") +fileprivate func make_swift_closure_TestModule_10TestModuleSqSb_SqSb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSqSb_SqSb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSqSb_SqSb { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModuleSqSb_SqSb(callbackValue, param0IsSome, param0Value) + return Optional.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSqSb_SqSb, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSqSb_SqSb") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSqSb_SqSb") +public func _invoke_swift_closure_TestModule_10TestModuleSqSb_SqSb(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSqSd_SqSd") +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSd_SqSd(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Float64) -> Void +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSd_SqSd(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSqSd_SqSd") +fileprivate func make_swift_closure_TestModule_10TestModuleSqSd_SqSd(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSqSd_SqSd(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSqSd_SqSd { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + invoke_js_callback_TestModule_10TestModuleSqSd_SqSd(callbackValue, param0IsSome, param0Value) + return Optional.bridgeJSLiftReturnFromSideChannel() + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSqSd_SqSd, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSqSd_SqSd") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSqSd_SqSd") +public func _invoke_swift_closure_TestModule_10TestModuleSqSd_SqSd(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Float64) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSqSf_SqSf") +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSf_SqSf(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Float32) -> Void +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSf_SqSf(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Float32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSqSf_SqSf") +fileprivate func make_swift_closure_TestModule_10TestModuleSqSf_SqSf(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSqSf_SqSf(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSqSf_SqSf { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + invoke_js_callback_TestModule_10TestModuleSqSf_SqSf(callbackValue, param0IsSome, param0Value) + return Optional.bridgeJSLiftReturnFromSideChannel() + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSqSf_SqSf, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSqSf_SqSf") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSqSf_SqSf") +public func _invoke_swift_closure_TestModule_10TestModuleSqSf_SqSf(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Float32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSqSi_SqSi") +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSi_SqSi(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Void +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSi_SqSi(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSqSi_SqSi") +fileprivate func make_swift_closure_TestModule_10TestModuleSqSi_SqSi(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSqSi_SqSi(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSqSi_SqSi { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + invoke_js_callback_TestModule_10TestModuleSqSi_SqSi(callbackValue, param0IsSome, param0Value) + return Optional.bridgeJSLiftReturnFromSideChannel() + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSqSi_SqSi, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSqSi_SqSi") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSqSi_SqSi") +public func _invoke_swift_closure_TestModule_10TestModuleSqSi_SqSi(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Direction: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_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 Theme: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension HttpStatus: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension APIResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> APIResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(Int.bridgeJSStackPop()) + case 2: + return .flag(Bool.bridgeJSStackPop()) + case 3: + return .rate(Float.bridgeJSStackPop()) + case 4: + return .precise(Double.bridgeJSStackPop()) + case 5: + return .info + default: + fatalError("Unknown APIResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .failure(let param0): + param0.bridgeJSStackPush() + return Int32(1) + case .flag(let param0): + param0.bridgeJSStackPush() + return Int32(2) + case .rate(let param0): + param0.bridgeJSStackPush() + return Int32(3) + case .precise(let param0): + param0.bridgeJSStackPush() + return Int32(4) + case .info: + return Int32(5) + } + } +} + +@_expose(wasm, "bjs_roundtripString") +@_cdecl("bjs_roundtripString") +public func _bjs_roundtripString(_ stringClosure: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripString(_: _BJS_Closure_10TestModuleSS_SS.bridgeJSLift(stringClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripInt") +@_cdecl("bjs_roundtripInt") +public func _bjs_roundtripInt(_ intClosure: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripInt(_: _BJS_Closure_10TestModuleSi_Si.bridgeJSLift(intClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripBool") +@_cdecl("bjs_roundtripBool") +public func _bjs_roundtripBool(_ boolClosure: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripBool(_: _BJS_Closure_10TestModuleSb_Sb.bridgeJSLift(boolClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripFloat") +@_cdecl("bjs_roundtripFloat") +public func _bjs_roundtripFloat(_ floatClosure: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripFloat(_: _BJS_Closure_10TestModuleSf_Sf.bridgeJSLift(floatClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripDouble") +@_cdecl("bjs_roundtripDouble") +public func _bjs_roundtripDouble(_ doubleClosure: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripDouble(_: _BJS_Closure_10TestModuleSd_Sd.bridgeJSLift(doubleClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripOptionalString") +@_cdecl("bjs_roundtripOptionalString") +public func _bjs_roundtripOptionalString(_ stringClosure: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripOptionalString(_: _BJS_Closure_10TestModuleSqSS_SqSS.bridgeJSLift(stringClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripOptionalInt") +@_cdecl("bjs_roundtripOptionalInt") +public func _bjs_roundtripOptionalInt(_ intClosure: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripOptionalInt(_: _BJS_Closure_10TestModuleSqSi_SqSi.bridgeJSLift(intClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripOptionalBool") +@_cdecl("bjs_roundtripOptionalBool") +public func _bjs_roundtripOptionalBool(_ boolClosure: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripOptionalBool(_: _BJS_Closure_10TestModuleSqSb_SqSb.bridgeJSLift(boolClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripOptionalFloat") +@_cdecl("bjs_roundtripOptionalFloat") +public func _bjs_roundtripOptionalFloat(_ floatClosure: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripOptionalFloat(_: _BJS_Closure_10TestModuleSqSf_SqSf.bridgeJSLift(floatClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripOptionalDouble") +@_cdecl("bjs_roundtripOptionalDouble") +public func _bjs_roundtripOptionalDouble(_ doubleClosure: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripOptionalDouble(_: _BJS_Closure_10TestModuleSqSd_SqSd.bridgeJSLift(doubleClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripPerson") +@_cdecl("bjs_roundtripPerson") +public func _bjs_roundtripPerson(_ personClosure: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripPerson(_: _BJS_Closure_10TestModule6PersonC_6PersonC.bridgeJSLift(personClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripOptionalPerson") +@_cdecl("bjs_roundtripOptionalPerson") +public func _bjs_roundtripOptionalPerson(_ personClosure: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripOptionalPerson(_: _BJS_Closure_10TestModuleSq6PersonC_Sq6PersonC.bridgeJSLift(personClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripDirection") +@_cdecl("bjs_roundtripDirection") +public func _bjs_roundtripDirection(_ callback: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripDirection(_: _BJS_Closure_10TestModule9DirectionO_9DirectionO.bridgeJSLift(callback)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripTheme") +@_cdecl("bjs_roundtripTheme") +public func _bjs_roundtripTheme(_ callback: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripTheme(_: _BJS_Closure_10TestModule5ThemeO_5ThemeO.bridgeJSLift(callback)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripHttpStatus") +@_cdecl("bjs_roundtripHttpStatus") +public func _bjs_roundtripHttpStatus(_ callback: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripHttpStatus(_: _BJS_Closure_10TestModule10HttpStatusO_10HttpStatusO.bridgeJSLift(callback)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripAPIResult") +@_cdecl("bjs_roundtripAPIResult") +public func _bjs_roundtripAPIResult(_ callback: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripAPIResult(_: _BJS_Closure_10TestModule9APIResultO_9APIResultO.bridgeJSLift(callback)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripOptionalDirection") +@_cdecl("bjs_roundtripOptionalDirection") +public func _bjs_roundtripOptionalDirection(_ callback: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripOptionalDirection(_: _BJS_Closure_10TestModuleSq9DirectionO_Sq9DirectionO.bridgeJSLift(callback)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripOptionalTheme") +@_cdecl("bjs_roundtripOptionalTheme") +public func _bjs_roundtripOptionalTheme(_ callback: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripOptionalTheme(_: _BJS_Closure_10TestModuleSq5ThemeO_Sq5ThemeO.bridgeJSLift(callback)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripOptionalHttpStatus") +@_cdecl("bjs_roundtripOptionalHttpStatus") +public func _bjs_roundtripOptionalHttpStatus(_ callback: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripOptionalHttpStatus(_: _BJS_Closure_10TestModuleSq10HttpStatusO_Sq10HttpStatusO.bridgeJSLift(callback)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripOptionalAPIResult") +@_cdecl("bjs_roundtripOptionalAPIResult") +public func _bjs_roundtripOptionalAPIResult(_ callback: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripOptionalAPIResult(_: _BJS_Closure_10TestModuleSq9APIResultO_Sq9APIResultO.bridgeJSLift(callback)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripOptionalDirection") +@_cdecl("bjs_roundtripOptionalDirection") +public func _bjs_roundtripOptionalDirection(_ callback: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripOptionalDirection(_: _BJS_Closure_10TestModuleSq9DirectionO_Sq9DirectionO.bridgeJSLift(callback)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Person_init") +@_cdecl("bjs_Person_init") +public func _bjs_Person_init(_ nameBytes: Int32, _ nameLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Person(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Person_deinit") +@_cdecl("bjs_Person_deinit") +public func _bjs_Person_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Person: ConvertibleToJSValue, _BridgedSwiftHeapObject { + public var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Person_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Person_wrap") +fileprivate func _bjs_Person_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Person_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_TestProcessor_init") +@_cdecl("bjs_TestProcessor_init") +public func _bjs_TestProcessor_init(_ transform: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = TestProcessor(transform: _BJS_Closure_10TestModuleSS_SS.bridgeJSLift(transform)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TestProcessor_deinit") +@_cdecl("bjs_TestProcessor_deinit") +public func _bjs_TestProcessor_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension TestProcessor: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_TestProcessor_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_TestProcessor_wrap") +fileprivate func _bjs_TestProcessor_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_TestProcessor_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.json new file mode 100644 index 000000000..0013c810c --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.json @@ -0,0 +1,94 @@ +{ + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "applyInt", + "parameters" : [ + { + "name" : "value", + "type" : { + "int" : { + + } + } + }, + { + "name" : "transform", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSi_Si", + "moduleName" : "TestModule", + "parameters" : [ + { + "int" : { + + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "name" : "makeAdder", + "parameters" : [ + { + "name" : "base", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSi_Si", + "moduleName" : "TestModule", + "parameters" : [ + { + "int" : { + + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "types" : [ + + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.swift new file mode 100644 index 000000000..c42c3b36f --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.swift @@ -0,0 +1,96 @@ +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSi_Si") +fileprivate func invoke_js_callback_TestModule_10TestModuleSi_Si(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSi_Si(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSi_Si") +fileprivate func make_swift_closure_TestModule_10TestModuleSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_10TestModuleSi_Si { + static func bridgeJSLift(_ callbackId: Int32) -> (Int) -> Int { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_TestModule_10TestModuleSi_Si(callbackValue, param0Value) + return Int.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Int) -> Int { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Int) -> Int) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModuleSi_Si, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSi_Si") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSi_Si") +public func _invoke_swift_closure_TestModule_10TestModuleSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Int) -> Int>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Int.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_applyInt") +fileprivate func bjs_applyInt(_ value: Int32, _ transform: Int32) -> Int32 +#else +fileprivate func bjs_applyInt(_ value: Int32, _ transform: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$applyInt(_ value: Int, _ transform: @escaping (Int) -> Int) throws(JSException) -> Int { + let valueValue = value.bridgeJSLowerParameter() + let transform = JSTypedClosure<(Int) -> Int>(transform) + let transformFuncRef = transform.bridgeJSLowerParameter() + let ret = withExtendedLifetime((transform)) { + bjs_applyInt(valueValue, transformFuncRef) + } + if let error = _swift_js_take_exception() { + throw error + } + return Int.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_makeAdder") +fileprivate func bjs_makeAdder(_ base: Int32) -> Int32 +#else +fileprivate func bjs_makeAdder(_ base: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$makeAdder(_ base: Int) throws(JSException) -> (Int) -> Int { + let baseValue = base.bridgeJSLowerParameter() + let ret = bjs_makeAdder(baseValue) + if let error = _swift_js_take_exception() { + throw error + } + return _BJS_Closure_10TestModuleSi_Si.bridgeJSLift(ret) +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.json new file mode 100644 index 000000000..00c6af5cb --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.json @@ -0,0 +1,589 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_Greeter_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_Greeter_greet", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "greet", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "Greeter", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "Greeter" + } + ], + "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" : [ + { + "abiName" : "bjs_roundtrip", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtrip", + "parameters" : [ + { + "label" : "_", + "name" : "session", + "type" : { + "swiftStruct" : { + "_0" : "Person" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Person" + } + } + }, + { + "abiName" : "bjs_roundtripContainer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripContainer", + "parameters" : [ + { + "label" : "_", + "name" : "container", + "type" : { + "swiftStruct" : { + "_0" : "Container" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Container" + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + { + "constructor" : { + "abiName" : "bjs_DataPoint_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "x", + "name" : "x", + "type" : { + "double" : { + + } + } + }, + { + "label" : "y", + "name" : "y", + "type" : { + "double" : { + + } + } + }, + { + "label" : "label", + "name" : "label", + "type" : { + "string" : { + + } + } + }, + { + "label" : "optCount", + "name" : "optCount", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "label" : "optFlag", + "name" : "optFlag", + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "DataPoint", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "x", + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "y", + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "label", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "optCount", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "optFlag", + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "DataPoint" + }, + { + "methods" : [ + + ], + "name" : "Address", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "street", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "city", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "zipCode", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "Address" + }, + { + "methods" : [ + + ], + "name" : "Person", + "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" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "Person" + }, + { + "methods" : [ + + ], + "name" : "Session", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "id", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "owner", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "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" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "Measurement" + }, + { + "methods" : [ + { + "abiName" : "bjs_ConfigStruct_static_update", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "update", + "parameters" : [ + { + "label" : "_", + "name" : "timeout", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "double" : { + + } + }, + "staticContext" : { + "structName" : { + "_0" : "ConfigStruct" + } + } + } + ], + "name" : "ConfigStruct", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : true, + "name" : "maxRetries", + "staticContext" : { + "structName" : { + "_0" : "ConfigStruct" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "defaultConfig", + "staticContext" : { + "structName" : { + "_0" : "ConfigStruct" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "timeout", + "staticContext" : { + "structName" : { + "_0" : "ConfigStruct" + } + }, + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "computedSetting", + "staticContext" : { + "structName" : { + "_0" : "ConfigStruct" + } + }, + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "ConfigStruct" + }, + { + "methods" : [ + + ], + "name" : "Container", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "object", + "type" : { + "jsObject" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "optionalObject", + "type" : { + "nullable" : { + "_0" : { + "jsObject" : { + + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "Container" + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.swift new file mode 100644 index 000000000..fb78c3fd0 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.swift @@ -0,0 +1,527 @@ +extension Precision: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension DataPoint: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> DataPoint { + let optFlag = Optional.bridgeJSStackPop() + let optCount = Optional.bridgeJSStackPop() + let label = String.bridgeJSStackPop() + let y = Double.bridgeJSStackPop() + let x = Double.bridgeJSStackPop() + return DataPoint(x: x, y: y, label: label, optCount: optCount, optFlag: optFlag) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.x.bridgeJSStackPush() + self.y.bridgeJSStackPush() + self.label.bridgeJSStackPush() + let __bjs_isSome_optCount = self.optCount != nil + if let __bjs_unwrapped_optCount = self.optCount { + __bjs_unwrapped_optCount.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_optCount ? 1 : 0) + let __bjs_isSome_optFlag = self.optFlag != nil + if let __bjs_unwrapped_optFlag = self.optFlag { + __bjs_unwrapped_optFlag.bridgeJSStackPush() + } + _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.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 { + #if arch(wasm32) + let ret = DataPoint(x: Double.bridgeJSLiftParameter(x), y: Double.bridgeJSLiftParameter(y), label: String.bridgeJSLiftParameter(labelBytes, labelLength), optCount: Optional.bridgeJSLiftParameter(optCountIsSome, optCountValue), optFlag: Optional.bridgeJSLiftParameter(optFlagIsSome, optFlagValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Address: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Address { + let zipCode = Optional.bridgeJSStackPop() + let city = String.bridgeJSStackPop() + let street = String.bridgeJSStackPop() + return Address(street: street, city: city, zipCode: zipCode) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.street.bridgeJSStackPush() + self.city.bridgeJSStackPush() + let __bjs_isSome_zipCode = self.zipCode != nil + if let __bjs_unwrapped_zipCode = self.zipCode { + __bjs_unwrapped_zipCode.bridgeJSStackPush() + } + _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) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> Person { + let email = Optional.bridgeJSStackPop() + let address = Address.bridgeJSStackPop() + let age = Int.bridgeJSStackPop() + let name = String.bridgeJSStackPop() + return Person(name: name, age: age, address: address, email: email) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.name.bridgeJSStackPush() + self.age.bridgeJSStackPush() + self.address.bridgeJSStackPush() + let __bjs_isSome_email = self.email != nil + if let __bjs_unwrapped_email = self.email { + __bjs_unwrapped_email.bridgeJSStackPush() + } + _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.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> Session { + let owner = Greeter.bridgeJSStackPop() + let id = Int.bridgeJSStackPop() + return Session(id: id, owner: owner) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.id.bridgeJSStackPush() + self.owner.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Session(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> Measurement { + let optionalPrecision = Optional.bridgeJSStackPop() + let precision = Precision.bridgeJSStackPop() + let value = Double.bridgeJSStackPop() + return Measurement(value: value, precision: precision, optionalPrecision: optionalPrecision) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.value.bridgeJSStackPush() + self.precision.bridgeJSStackPush() + let __bjs_isSome_optionalPrecision = self.optionalPrecision != nil + if let __bjs_unwrapped_optionalPrecision = self.optionalPrecision { + __bjs_unwrapped_optionalPrecision.bridgeJSStackPush() + } + _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.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> ConfigStruct { + return ConfigStruct() + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_ConfigStruct(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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") +public func _bjs_ConfigStruct_static_maxRetries_get() -> Int32 { + #if arch(wasm32) + let ret = ConfigStruct.maxRetries + return ret.bridgeJSLowerReturn() + #else + 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") +@_cdecl("bjs_ConfigStruct_static_defaultConfig_set") +public func _bjs_ConfigStruct_static_defaultConfig_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + ConfigStruct.defaultConfig = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConfigStruct_static_timeout_get") +@_cdecl("bjs_ConfigStruct_static_timeout_get") +public func _bjs_ConfigStruct_static_timeout_get() -> Float64 { + #if arch(wasm32) + let ret = ConfigStruct.timeout + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConfigStruct_static_timeout_set") +@_cdecl("bjs_ConfigStruct_static_timeout_set") +public func _bjs_ConfigStruct_static_timeout_set(_ value: Float64) -> Void { + #if arch(wasm32) + ConfigStruct.timeout = Double.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConfigStruct_static_computedSetting_get") +@_cdecl("bjs_ConfigStruct_static_computedSetting_get") +public func _bjs_ConfigStruct_static_computedSetting_get() -> Void { + #if arch(wasm32) + let ret = ConfigStruct.computedSetting + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConfigStruct_static_update") +@_cdecl("bjs_ConfigStruct_static_update") +public func _bjs_ConfigStruct_static_update(_ timeout: Float64) -> Float64 { + #if arch(wasm32) + let ret = ConfigStruct.update(_: Double.bridgeJSLiftParameter(timeout)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Container: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Container { + let optionalObject = Optional.bridgeJSStackPop() + let object = JSObject.bridgeJSStackPop() + return Container(object: object, optionalObject: optionalObject) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.object.bridgeJSStackPush() + let __bjs_isSome_optionalObject = self.optionalObject != nil + if let __bjs_unwrapped_optionalObject = self.optionalObject { + __bjs_unwrapped_optionalObject.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_optionalObject ? 1 : 0) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Container(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Container())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Container") +fileprivate func _bjs_struct_lower_Container(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_Container(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Container") +fileprivate func _bjs_struct_lift_Container() -> Int32 +#else +fileprivate func _bjs_struct_lift_Container() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_roundtrip") +@_cdecl("bjs_roundtrip") +public func _bjs_roundtrip() -> Void { + #if arch(wasm32) + let ret = roundtrip(_: Person.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripContainer") +@_cdecl("bjs_roundtripContainer") +public func _bjs_roundtripContainer() -> Void { + #if arch(wasm32) + let ret = roundtripContainer(_: Container.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_init") +@_cdecl("bjs_Greeter_init") +public func _bjs_Greeter_init(_ nameBytes: Int32, _ nameLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Greeter(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_greet") +@_cdecl("bjs_Greeter_greet") +public func _bjs_Greeter_greet(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Greeter.bridgeJSLiftParameter(_self).greet() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_name_get") +@_cdecl("bjs_Greeter_name_get") +public func _bjs_Greeter_name_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Greeter.bridgeJSLiftParameter(_self).name + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_name_set") +@_cdecl("bjs_Greeter_name_set") +public func _bjs_Greeter_name_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + Greeter.bridgeJSLiftParameter(_self).name = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_deinit") +@_cdecl("bjs_Greeter_deinit") +public func _bjs_Greeter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Greeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Greeter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Greeter_wrap") +fileprivate func _bjs_Greeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Greeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStructImports.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStructImports.json new file mode 100644 index 000000000..50af441a9 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStructImports.json @@ -0,0 +1,94 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + { + "methods" : [ + + ], + "name" : "Point", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "x", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "y", + "type" : { + "int" : { + + } + } + } + ], + "swiftCallName" : "Point" + } + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "translate", + "parameters" : [ + { + "name" : "point", + "type" : { + "swiftStruct" : { + "_0" : "Point" + } + } + }, + { + "name" : "dx", + "type" : { + "int" : { + + } + } + }, + { + "name" : "dy", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Point" + } + } + } + ], + "types" : [ + + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStructImports.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStructImports.swift new file mode 100644 index 000000000..089912afe --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStructImports.swift @@ -0,0 +1,64 @@ +extension Point: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Point { + let y = Int.bridgeJSStackPop() + let x = Int.bridgeJSStackPop() + return Point(x: x, y: y) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.x.bridgeJSStackPush() + self.y.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", 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/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Throws.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Throws.json new file mode 100644 index 000000000..02796479f --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Throws.json @@ -0,0 +1,37 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_throwsSomething", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "throwsSomething", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Throws.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Throws.swift similarity index 75% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Throws.swift rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Throws.swift index 8b865b7d7..37f6d9c96 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Throws.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Throws.swift @@ -1,11 +1,3 @@ -// 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(BridgeJS) import JavaScriptKit - @_expose(wasm, "bjs_throwsSomething") @_cdecl("bjs_throwsSomething") public func _bjs_throwsSomething() -> Void { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/UnsafePointer.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/UnsafePointer.json new file mode 100644 index 000000000..1eb9e47ec --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/UnsafePointer.json @@ -0,0 +1,416 @@ +{ + "exported" : { + "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" + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/UnsafePointer.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/UnsafePointer.swift new file mode 100644 index 000000000..a4f372e9b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/UnsafePointer.swift @@ -0,0 +1,177 @@ +extension PointerFields: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> PointerFields { + let mutPtr = UnsafeMutablePointer.bridgeJSStackPop() + let ptr = UnsafePointer.bridgeJSStackPop() + let opaque = OpaquePointer.bridgeJSStackPop() + let mutRaw = UnsafeMutableRawPointer.bridgeJSStackPop() + let raw = UnsafeRawPointer.bridgeJSStackPop() + return PointerFields(raw: raw, mutRaw: mutRaw, opaque: opaque, ptr: ptr, mutPtr: mutPtr) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.raw.bridgeJSStackPush() + self.mutRaw.bridgeJSStackPush() + self.opaque.bridgeJSStackPush() + self.ptr.bridgeJSStackPush() + self.mutPtr.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_PointerFields(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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__/BridgeJSCodegenTests/VoidParameterVoidReturn.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/VoidParameterVoidReturn.json new file mode 100644 index 000000000..14da32841 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/VoidParameterVoidReturn.json @@ -0,0 +1,59 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_check", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "check", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + { + "name" : "check", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + } + ], + "types" : [ + + ] + } + ] + }, + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/VoidParameterVoidReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/VoidParameterVoidReturn.swift new file mode 100644 index 000000000..3fa9619f8 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/VoidParameterVoidReturn.swift @@ -0,0 +1,25 @@ +@_expose(wasm, "bjs_check") +@_cdecl("bjs_check") +public func _bjs_check() -> Void { + #if arch(wasm32) + check() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_check") +fileprivate func bjs_check() -> Void +#else +fileprivate func bjs_check() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$check() throws(JSException) -> Void { + bjs_check() + if let error = _swift_js_take_exception() { + throw error + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.js deleted file mode 100644 index c122f1797..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.js +++ /dev/null @@ -1,92 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_checkArray"] = function bjs_checkArray(a) { - try { - imports.checkArray(swift.memory.getObject(a)); - } catch (error) { - setException(error); - } - } - TestModule["bjs_checkArrayWithLength"] = function bjs_checkArrayWithLength(a, b) { - try { - imports.checkArrayWithLength(swift.memory.getObject(a), b); - } catch (error) { - setException(error); - } - } - TestModule["bjs_checkArray"] = function bjs_checkArray(a) { - try { - imports.checkArray(swift.memory.getObject(a)); - } 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; - - return { - - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.d.ts new file mode 100644 index 000000000..8dc76156b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.d.ts @@ -0,0 +1,86 @@ +// 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[][]; + processJSObjectArray(objects: any[]): any[]; + processOptionalJSObjectArray(objects: (any | null)[]): (any | null)[]; + processNestedJSObjectArray(objects: any[][]): any[][]; + Direction: DirectionObject + Status: StatusObject +} +export type Imports = { + checkArray(a: any): void; + checkArrayWithLength(a: any, b: number): void; + importProcessNumbers(values: number[]): void; + importGetNumbers(): number[]; + importTransformNumbers(values: number[]): number[]; + importProcessStrings(values: string[]): string[]; + importProcessBooleans(values: boolean[]): boolean[]; +} +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.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js new file mode 100644 index 000000000..7db995321 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js @@ -0,0 +1,1022 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createPointHelpers = () => { + return () => ({ + lower: (value) => { + f64Stack.push(value.x); + f64Stack.push(value.y); + return { cleanup: undefined }; + }, + lift: () => { + const f64 = f64Stack.pop(); + const f641 = f64Stack.pop(); + return { x: f641, y: f64 }; + } + }); + }; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_struct_lower_Point"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.Point.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_Point"] = function() { + const value = structHelpers.Point.lift(); + 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_Item_wrap"] = function(pointer) { + const obj = _exports['Item'].__construct(pointer); + return swift.memory.retain(obj); + }; + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_checkArray"] = function bjs_checkArray(a) { + try { + imports.checkArray(swift.memory.getObject(a)); + } catch (error) { + setException(error); + } + } + TestModule["bjs_checkArrayWithLength"] = function bjs_checkArrayWithLength(a, b) { + try { + imports.checkArrayWithLength(swift.memory.getObject(a), b); + } catch (error) { + setException(error); + } + } + TestModule["bjs_importProcessNumbers"] = function bjs_importProcessNumbers() { + try { + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const f64 = f64Stack.pop(); + arrayResult.push(f64); + } + arrayResult.reverse(); + imports.importProcessNumbers(arrayResult); + } catch (error) { + setException(error); + } + } + TestModule["bjs_importGetNumbers"] = function bjs_importGetNumbers() { + try { + let ret = imports.importGetNumbers(); + const arrayCleanups = []; + for (const elem of ret) { + f64Stack.push(elem); + } + i32Stack.push(ret.length); + } catch (error) { + setException(error); + } + } + TestModule["bjs_importTransformNumbers"] = function bjs_importTransformNumbers() { + try { + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const f64 = f64Stack.pop(); + arrayResult.push(f64); + } + arrayResult.reverse(); + let ret = imports.importTransformNumbers(arrayResult); + const arrayCleanups = []; + for (const elem of ret) { + f64Stack.push(elem); + } + i32Stack.push(ret.length); + } catch (error) { + setException(error); + } + } + TestModule["bjs_importProcessStrings"] = function bjs_importProcessStrings() { + try { + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const string = strStack.pop(); + arrayResult.push(string); + } + arrayResult.reverse(); + let ret = imports.importProcessStrings(arrayResult); + const arrayCleanups = []; + for (const elem of ret) { + const bytes = textEncoder.encode(elem); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + } + i32Stack.push(ret.length); + } catch (error) { + setException(error); + } + } + TestModule["bjs_importProcessBooleans"] = function bjs_importProcessBooleans() { + try { + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const bool = i32Stack.pop() !== 0; + arrayResult.push(bool); + } + arrayResult.reverse(); + let ret = imports.importProcessBooleans(arrayResult); + const arrayCleanups = []; + for (const elem of ret) { + i32Stack.push(elem ? 1 : 0); + } + i32Stack.push(ret.length); + } 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 swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class Item extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Item_deinit, Item.prototype); + } + + } + const PointHelpers = __bjs_createPointHelpers()(); + structHelpers.Point = PointHelpers; + + const exports = { + Item, + processIntArray: function bjs_processIntArray(values) { + const arrayCleanups = []; + for (const elem of values) { + i32Stack.push((elem | 0)); + } + i32Stack.push(values.length); + instance.exports.bjs_processIntArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.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); + i32Stack.push(bytes.length); + i32Stack.push(id); + } + i32Stack.push(values.length); + instance.exports.bjs_processStringArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const string = strStack.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) { + f64Stack.push(elem); + } + i32Stack.push(values.length); + instance.exports.bjs_processDoubleArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const f64 = f64Stack.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) { + i32Stack.push(elem ? 1 : 0); + } + i32Stack.push(values.length); + instance.exports.bjs_processBoolArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const bool = i32Stack.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: structCleanup } = structHelpers.Point.lower(elem); + arrayCleanups.push(() => { + if (structCleanup) { structCleanup(); } + }); + } + i32Stack.push(points.length); + instance.exports.bjs_processPointArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const struct = structHelpers.Point.lift(); + arrayResult.push(struct); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processDirectionArray: function bjs_processDirectionArray(directions) { + const arrayCleanups = []; + for (const elem of directions) { + i32Stack.push((elem | 0)); + } + i32Stack.push(directions.length); + instance.exports.bjs_processDirectionArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const caseId = i32Stack.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) { + i32Stack.push((elem | 0)); + } + i32Stack.push(statuses.length); + instance.exports.bjs_processStatusArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const rawValue = i32Stack.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) { + i32Stack.push((elem | 0)); + } + i32Stack.push(values.length); + const ret = instance.exports.bjs_sumIntArray(); + for (const cleanup of arrayCleanups) { cleanup(); } + return ret; + }, + findFirstPoint: function bjs_findFirstPoint(points, matching) { + const arrayCleanups = []; + for (const elem of points) { + const { cleanup: structCleanup } = structHelpers.Point.lower(elem); + arrayCleanups.push(() => { + if (structCleanup) { structCleanup(); } + }); + } + i32Stack.push(points.length); + const matchingBytes = textEncoder.encode(matching); + const matchingId = swift.memory.retain(matchingBytes); + instance.exports.bjs_findFirstPoint(matchingId, matchingBytes.length); + const structValue = structHelpers.Point.lift(); + for (const cleanup of arrayCleanups) { cleanup(); } + return structValue; + }, + processUnsafeRawPointerArray: function bjs_processUnsafeRawPointerArray(values) { + const arrayCleanups = []; + for (const elem of values) { + ptrStack.push((elem | 0)); + } + i32Stack.push(values.length); + instance.exports.bjs_processUnsafeRawPointerArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const pointer = ptrStack.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) { + ptrStack.push((elem | 0)); + } + i32Stack.push(values.length); + instance.exports.bjs_processUnsafeMutableRawPointerArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const pointer = ptrStack.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) { + ptrStack.push((elem | 0)); + } + i32Stack.push(values.length); + instance.exports.bjs_processOpaquePointerArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const pointer = ptrStack.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) { + i32Stack.push((elem | 0)); + } else { + i32Stack.push(0); + } + i32Stack.push(isSome); + } + i32Stack.push(values.length); + instance.exports.bjs_processOptionalIntArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const isSome1 = i32Stack.pop(); + let optValue; + if (isSome1 === 0) { + optValue = null; + } else { + const int = i32Stack.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); + i32Stack.push(bytes.length); + i32Stack.push(id); + } else { + i32Stack.push(0); + i32Stack.push(0); + } + i32Stack.push(isSome); + } + i32Stack.push(values.length); + instance.exports.bjs_processOptionalStringArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const isSome1 = i32Stack.pop(); + let optValue; + if (isSome1 === 0) { + optValue = null; + } else { + const string = strStack.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) { + i32Stack.push((elem | 0)); + } + i32Stack.push(values.length); + valuesCleanups.push(() => { for (const cleanup of arrayCleanups) { cleanup(); } }); + } + i32Stack.push(+isSome); + instance.exports.bjs_processOptionalArray(); + const isSome1 = i32Stack.pop(); + let optResult; + if (isSome1) { + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.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: structCleanup } = structHelpers.Point.lower(elem); + arrayCleanups.push(() => { if (structCleanup) { structCleanup(); } }); + } else { + } + i32Stack.push(isSome); + } + i32Stack.push(points.length); + instance.exports.bjs_processOptionalPointArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const isSome1 = i32Stack.pop(); + let optValue; + if (isSome1 === 0) { + optValue = null; + } else { + const struct = structHelpers.Point.lift(); + 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) { + i32Stack.push((elem | 0)); + } else { + i32Stack.push(0); + } + i32Stack.push(isSome); + } + i32Stack.push(directions.length); + instance.exports.bjs_processOptionalDirectionArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const isSome1 = i32Stack.pop(); + let optValue; + if (isSome1 === 0) { + optValue = null; + } else { + const caseId = i32Stack.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) { + i32Stack.push((elem | 0)); + } else { + i32Stack.push(0); + } + i32Stack.push(isSome); + } + i32Stack.push(statuses.length); + instance.exports.bjs_processOptionalStatusArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const isSome1 = i32Stack.pop(); + let optValue; + if (isSome1 === 0) { + optValue = null; + } else { + const rawValue = i32Stack.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) { + i32Stack.push((elem1 | 0)); + } + i32Stack.push(elem.length); + arrayCleanups.push(() => { + for (const cleanup of arrayCleanups1) { cleanup(); } + }); + } + i32Stack.push(values.length); + instance.exports.bjs_processNestedIntArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const arrayLen1 = i32Stack.pop(); + const arrayResult1 = []; + for (let i1 = 0; i1 < arrayLen1; i1++) { + const int = i32Stack.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); + i32Stack.push(bytes.length); + i32Stack.push(id); + } + i32Stack.push(elem.length); + arrayCleanups.push(() => { + for (const cleanup of arrayCleanups1) { cleanup(); } + }); + } + i32Stack.push(values.length); + instance.exports.bjs_processNestedStringArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const arrayLen1 = i32Stack.pop(); + const arrayResult1 = []; + for (let i1 = 0; i1 < arrayLen1; i1++) { + const string = strStack.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: structCleanup } = structHelpers.Point.lower(elem1); + arrayCleanups1.push(() => { + if (structCleanup) { structCleanup(); } + }); + } + i32Stack.push(elem.length); + arrayCleanups.push(() => { + for (const cleanup of arrayCleanups1) { cleanup(); } + }); + } + i32Stack.push(points.length); + instance.exports.bjs_processNestedPointArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const arrayLen1 = i32Stack.pop(); + const arrayResult1 = []; + for (let i1 = 0; i1 < arrayLen1; i1++) { + const struct = structHelpers.Point.lift(); + 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) { + ptrStack.push(elem.pointer); + } + i32Stack.push(items.length); + instance.exports.bjs_processItemArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const ptr = ptrStack.pop(); + const obj = _exports['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) { + ptrStack.push(elem1.pointer); + } + i32Stack.push(elem.length); + arrayCleanups.push(() => { + for (const cleanup of arrayCleanups1) { cleanup(); } + }); + } + i32Stack.push(items.length); + instance.exports.bjs_processNestedItemArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const arrayLen1 = i32Stack.pop(); + const arrayResult1 = []; + for (let i1 = 0; i1 < arrayLen1; i1++) { + const ptr = ptrStack.pop(); + const obj = _exports['Item'].__construct(ptr); + arrayResult1.push(obj); + } + arrayResult1.reverse(); + arrayResult.push(arrayResult1); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processJSObjectArray: function bjs_processJSObjectArray(objects) { + const arrayCleanups = []; + for (const elem of objects) { + const objId = swift.memory.retain(elem); + i32Stack.push(objId); + } + i32Stack.push(objects.length); + instance.exports.bjs_processJSObjectArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const objId1 = i32Stack.pop(); + const obj = swift.memory.getObject(objId1); + swift.memory.release(objId1); + arrayResult.push(obj); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processOptionalJSObjectArray: function bjs_processOptionalJSObjectArray(objects) { + const arrayCleanups = []; + for (const elem of objects) { + const isSome = elem != null ? 1 : 0; + if (isSome) { + const objId = swift.memory.retain(elem); + i32Stack.push(objId); + } else { + i32Stack.push(0); + } + i32Stack.push(isSome); + } + i32Stack.push(objects.length); + instance.exports.bjs_processOptionalJSObjectArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const isSome1 = i32Stack.pop(); + let optValue; + if (isSome1 === 0) { + optValue = null; + } else { + const objId1 = i32Stack.pop(); + const obj = swift.memory.getObject(objId1); + swift.memory.release(objId1); + optValue = obj; + } + arrayResult.push(optValue); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processNestedJSObjectArray: function bjs_processNestedJSObjectArray(objects) { + const arrayCleanups = []; + for (const elem of objects) { + const arrayCleanups1 = []; + for (const elem1 of elem) { + const objId = swift.memory.retain(elem1); + i32Stack.push(objId); + } + i32Stack.push(elem.length); + arrayCleanups.push(() => { + for (const cleanup of arrayCleanups1) { cleanup(); } + }); + } + i32Stack.push(objects.length); + instance.exports.bjs_processNestedJSObjectArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const arrayLen1 = i32Stack.pop(); + const arrayResult1 = []; + for (let i1 = 0; i1 < arrayLen1; i1++) { + const objId1 = i32Stack.pop(); + const obj = swift.memory.getObject(objId1); + swift.memory.release(objId1); + 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 deleted file mode 100644 index 1da2f58ee..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js +++ /dev/null @@ -1,115 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - - }, - 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; - - return { - asyncReturnVoid: function bjs_asyncReturnVoid() { - const retId = instance.exports.bjs_asyncReturnVoid(); - const ret = swift.memory.getObject(retId); - swift.memory.release(retId); - return ret; - }, - asyncRoundTripInt: function bjs_asyncRoundTripInt(v) { - const retId = instance.exports.bjs_asyncRoundTripInt(v); - const ret = swift.memory.getObject(retId); - swift.memory.release(retId); - return ret; - }, - asyncRoundTripString: function bjs_asyncRoundTripString(v) { - const vBytes = textEncoder.encode(v); - const vId = swift.memory.retain(vBytes); - const retId = instance.exports.bjs_asyncRoundTripString(vId, vBytes.length); - const ret = swift.memory.getObject(retId); - swift.memory.release(retId); - swift.memory.release(vId); - return ret; - }, - asyncRoundTripBool: function bjs_asyncRoundTripBool(v) { - const retId = instance.exports.bjs_asyncRoundTripBool(v); - const ret = swift.memory.getObject(retId); - swift.memory.release(retId); - return ret; - }, - asyncRoundTripFloat: function bjs_asyncRoundTripFloat(v) { - const retId = instance.exports.bjs_asyncRoundTripFloat(v); - const ret = swift.memory.getObject(retId); - swift.memory.release(retId); - return ret; - }, - asyncRoundTripDouble: function bjs_asyncRoundTripDouble(v) { - const retId = instance.exports.bjs_asyncRoundTripDouble(v); - const ret = swift.memory.getObject(retId); - swift.memory.release(retId); - return ret; - }, - asyncRoundTripJSObject: function bjs_asyncRoundTripJSObject(v) { - const retId = instance.exports.bjs_asyncRoundTripJSObject(swift.memory.retain(v)); - const ret = swift.memory.getObject(retId); - swift.memory.release(retId); - return ret; - }, - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.d.ts deleted file mode 100644 index dea0bd186..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -// 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 type Exports = { -} -export type Imports = { - asyncReturnVoid(): JSPromise; - asyncRoundTripInt(v: number): JSPromise; - asyncRoundTripString(v: string): JSPromise; - asyncRoundTripBool(v: boolean): JSPromise; - asyncRoundTripFloat(v: number): JSPromise; - asyncRoundTripDouble(v: number): JSPromise; - asyncRoundTripJSObject(v: any): JSPromise; -} -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/Async.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js deleted file mode 100644 index 21d11fa4d..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js +++ /dev/null @@ -1,136 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_asyncReturnVoid"] = function bjs_asyncReturnVoid() { - try { - let ret = imports.asyncReturnVoid(); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_asyncRoundTripInt"] = function bjs_asyncRoundTripInt(v) { - try { - let ret = imports.asyncRoundTripInt(v); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_asyncRoundTripString"] = function bjs_asyncRoundTripString(v) { - try { - const vObject = swift.memory.getObject(v); - swift.memory.release(v); - let ret = imports.asyncRoundTripString(vObject); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_asyncRoundTripBool"] = function bjs_asyncRoundTripBool(v) { - try { - let ret = imports.asyncRoundTripBool(v); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_asyncRoundTripFloat"] = function bjs_asyncRoundTripFloat(v) { - try { - let ret = imports.asyncRoundTripFloat(v); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_asyncRoundTripDouble"] = function bjs_asyncRoundTripDouble(v) { - try { - let ret = imports.asyncRoundTripDouble(v); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_asyncRoundTripJSObject"] = function bjs_asyncRoundTripJSObject(v) { - try { - let ret = imports.asyncRoundTripJSObject(swift.memory.getObject(v)); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 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; - - return { - - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.d.ts similarity index 100% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.d.ts rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.d.ts diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js new file mode 100644 index 000000000..bd57f0fd4 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js @@ -0,0 +1,260 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + }, + 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 = { + asyncReturnVoid: function bjs_asyncReturnVoid() { + const ret = instance.exports.bjs_asyncReturnVoid(); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripInt: function bjs_asyncRoundTripInt(v) { + const ret = instance.exports.bjs_asyncRoundTripInt(v); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripString: function bjs_asyncRoundTripString(v) { + const vBytes = textEncoder.encode(v); + const vId = swift.memory.retain(vBytes); + const ret = instance.exports.bjs_asyncRoundTripString(vId, vBytes.length); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripBool: function bjs_asyncRoundTripBool(v) { + const ret = instance.exports.bjs_asyncRoundTripBool(v); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripFloat: function bjs_asyncRoundTripFloat(v) { + const ret = instance.exports.bjs_asyncRoundTripFloat(v); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripDouble: function bjs_asyncRoundTripDouble(v) { + const ret = instance.exports.bjs_asyncRoundTripDouble(v); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripJSObject: function bjs_asyncRoundTripJSObject(v) { + const ret = instance.exports.bjs_asyncRoundTripJSObject(swift.memory.retain(v)); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.d.ts new file mode 100644 index 000000000..ac5658eb3 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.d.ts @@ -0,0 +1,165 @@ +// 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 StatusValues: { + readonly Active: 0; + readonly Inactive: 1; + readonly Pending: 2; +}; +export type StatusTag = typeof StatusValues[keyof typeof StatusValues]; + +export interface Config { + name: string; + value: number; + enabled: boolean; +} +export interface MathOperations { + baseValue: number; + /** + * @param b - Optional parameter (default: 10.0) + */ + add(a: number, b?: number): number; + multiply(a: number, b: number): number; +} +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 DefaultGreeter extends SwiftHeapObject { + name: string; +} +export interface EmptyGreeter extends SwiftHeapObject { +} +export interface ConstructorDefaults extends SwiftHeapObject { + name: string; + count: number; + enabled: boolean; + status: StatusTag; + tag: string | null; +} +export type Exports = { + DefaultGreeter: { + new(name: string): DefaultGreeter; + } + EmptyGreeter: { + new(): EmptyGreeter; + } + ConstructorDefaults: { + /** + * @param name - Optional parameter (default: "Default") + * @param count - Optional parameter (default: 42) + * @param enabled - Optional parameter (default: true) + * @param status - Optional parameter (default: Status.Active) + * @param tag - Optional parameter (default: null) + */ + new(name?: string, count?: number, enabled?: boolean, status?: StatusTag, tag?: string | null): ConstructorDefaults; + } + /** + * @param message - Optional parameter (default: "Hello World") + */ + testStringDefault(message?: string): string; + /** + * @param value - Optional parameter (default: -42) + */ + testNegativeIntDefault(value?: number): number; + /** + * @param flag - Optional parameter (default: true) + */ + testBoolDefault(flag?: boolean): boolean; + /** + * @param temp - Optional parameter (default: -273.15) + */ + testNegativeFloatDefault(temp?: number): number; + /** + * @param precision - Optional parameter (default: 2.718) + */ + testDoubleDefault(precision?: number): number; + /** + * @param name - Optional parameter (default: null) + */ + testOptionalDefault(name?: string | null): string | null; + /** + * @param greeting - Optional parameter (default: "Hi") + */ + testOptionalStringDefault(greeting?: string | null): string | null; + /** + * @param title - Optional parameter (default: "Default Title") + * @param count - Optional parameter (default: 10) + * @param enabled - Optional parameter (default: false) + */ + testMultipleDefaults(title?: string, count?: number, enabled?: boolean): string; + /** + * @param status - Optional parameter (default: Status.Active) + */ + testEnumDefault(status?: StatusTag): StatusTag; + /** + * @param greeter - Optional parameter (default: new DefaultGreeter("DefaultUser")) + */ + testComplexInit(greeter?: DefaultGreeter): DefaultGreeter; + /** + * @param greeter - Optional parameter (default: new EmptyGreeter()) + */ + testEmptyInit(greeter?: EmptyGreeter): EmptyGreeter; + /** + * @param point - Optional parameter (default: null) + */ + testOptionalStructDefault(point?: Config | null): Config | null; + /** + * @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: { + /** + * @param baseValue - Optional parameter (default: 0.0) + */ + init(baseValue?: number): MathOperations; + /** + * @param b - Optional parameter (default: 5.0) + */ + subtract(a: number, b?: number): number; + } +} +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/DefaultParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js new file mode 100644 index 000000000..a89b07fc3 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js @@ -0,0 +1,660 @@ +// 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 StatusValues = { + Active: 0, + Inactive: 1, + Pending: 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createConfigHelpers = () => { + return () => ({ + lower: (value) => { + const bytes = textEncoder.encode(value.name); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + i32Stack.push((value.value | 0)); + i32Stack.push(value.enabled ? 1 : 0); + return { cleanup: undefined }; + }, + lift: () => { + const bool = i32Stack.pop() !== 0; + const int = i32Stack.pop(); + const string = strStack.pop(); + return { name: string, value: int, enabled: bool }; + } + }); + }; + const __bjs_createMathOperationsHelpers = () => { + return () => ({ + lower: (value) => { + f64Stack.push(value.baseValue); + return { cleanup: undefined }; + }, + lift: () => { + const f64 = f64Stack.pop(); + const instance1 = { baseValue: f64 }; + instance1.add = function(a, b = 10.0) { + const { cleanup: structCleanup } = structHelpers.MathOperations.lower(this); + const ret = instance.exports.bjs_MathOperations_add(a, b); + if (structCleanup) { structCleanup(); } + return ret; + }.bind(instance1); + instance1.multiply = function(a, b) { + const { cleanup: structCleanup } = structHelpers.MathOperations.lower(this); + const ret = instance.exports.bjs_MathOperations_multiply(a, b); + if (structCleanup) { structCleanup(); } + return ret; + }.bind(instance1); + return instance1; + } + }); + }; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_struct_lower_Config"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.Config.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_Config"] = function() { + const value = structHelpers.Config.lift(); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_MathOperations"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.MathOperations.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_MathOperations"] = function() { + const value = structHelpers.MathOperations.lift(); + 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_ConstructorDefaults_wrap"] = function(pointer) { + const obj = _exports['ConstructorDefaults'].__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_DefaultGreeter_wrap"] = function(pointer) { + const obj = _exports['DefaultGreeter'].__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_EmptyGreeter_wrap"] = function(pointer) { + const obj = _exports['EmptyGreeter'].__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; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class DefaultGreeter extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_DefaultGreeter_deinit, DefaultGreeter.prototype); + } + + constructor(name) { + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + const ret = instance.exports.bjs_DefaultGreeter_init(nameId, nameBytes.length); + return DefaultGreeter.__construct(ret); + } + get name() { + instance.exports.bjs_DefaultGreeter_name_get(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + set name(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_DefaultGreeter_name_set(this.pointer, valueId, valueBytes.length); + } + } + class EmptyGreeter extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_EmptyGreeter_deinit, EmptyGreeter.prototype); + } + + constructor() { + const ret = instance.exports.bjs_EmptyGreeter_init(); + return EmptyGreeter.__construct(ret); + } + } + class ConstructorDefaults extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_ConstructorDefaults_deinit, ConstructorDefaults.prototype); + } + + constructor(name = "Default", count = 42, enabled = true, status = StatusValues.Active, tag = null) { + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + const isSome = tag != null; + let tagId, tagBytes; + if (isSome) { + tagBytes = textEncoder.encode(tag); + tagId = swift.memory.retain(tagBytes); + } + const ret = instance.exports.bjs_ConstructorDefaults_init(nameId, nameBytes.length, count, enabled, status, +isSome, isSome ? tagId : 0, isSome ? tagBytes.length : 0); + return ConstructorDefaults.__construct(ret); + } + get name() { + instance.exports.bjs_ConstructorDefaults_name_get(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + set name(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_ConstructorDefaults_name_set(this.pointer, valueId, valueBytes.length); + } + get count() { + const ret = instance.exports.bjs_ConstructorDefaults_count_get(this.pointer); + return ret; + } + set count(value) { + instance.exports.bjs_ConstructorDefaults_count_set(this.pointer, value); + } + get enabled() { + const ret = instance.exports.bjs_ConstructorDefaults_enabled_get(this.pointer); + return ret !== 0; + } + set enabled(value) { + instance.exports.bjs_ConstructorDefaults_enabled_set(this.pointer, value); + } + get status() { + const ret = instance.exports.bjs_ConstructorDefaults_status_get(this.pointer); + return ret; + } + set status(value) { + instance.exports.bjs_ConstructorDefaults_status_set(this.pointer, value); + } + get tag() { + instance.exports.bjs_ConstructorDefaults_tag_get(this.pointer); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + } + set tag(value) { + const isSome = value != null; + let valueId, valueBytes; + if (isSome) { + valueBytes = textEncoder.encode(value); + valueId = swift.memory.retain(valueBytes); + } + instance.exports.bjs_ConstructorDefaults_tag_set(this.pointer, +isSome, isSome ? valueId : 0, isSome ? valueBytes.length : 0); + } + } + const ConfigHelpers = __bjs_createConfigHelpers()(); + structHelpers.Config = ConfigHelpers; + + const MathOperationsHelpers = __bjs_createMathOperationsHelpers()(); + structHelpers.MathOperations = MathOperationsHelpers; + + const exports = { + DefaultGreeter, + EmptyGreeter, + ConstructorDefaults, + testStringDefault: function bjs_testStringDefault(message = "Hello World") { + const messageBytes = textEncoder.encode(message); + const messageId = swift.memory.retain(messageBytes); + instance.exports.bjs_testStringDefault(messageId, messageBytes.length); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + testNegativeIntDefault: function bjs_testNegativeIntDefault(value = -42) { + const ret = instance.exports.bjs_testNegativeIntDefault(value); + return ret; + }, + testBoolDefault: function bjs_testBoolDefault(flag = true) { + const ret = instance.exports.bjs_testBoolDefault(flag); + return ret !== 0; + }, + testNegativeFloatDefault: function bjs_testNegativeFloatDefault(temp = -273.15) { + const ret = instance.exports.bjs_testNegativeFloatDefault(temp); + return ret; + }, + testDoubleDefault: function bjs_testDoubleDefault(precision = 2.718) { + const ret = instance.exports.bjs_testDoubleDefault(precision); + return ret; + }, + testOptionalDefault: function bjs_testOptionalDefault(name = null) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + instance.exports.bjs_testOptionalDefault(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + }, + testOptionalStringDefault: function bjs_testOptionalStringDefault(greeting = "Hi") { + const isSome = greeting != null; + let greetingId, greetingBytes; + if (isSome) { + greetingBytes = textEncoder.encode(greeting); + greetingId = swift.memory.retain(greetingBytes); + } + instance.exports.bjs_testOptionalStringDefault(+isSome, isSome ? greetingId : 0, isSome ? greetingBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + }, + testMultipleDefaults: function bjs_testMultipleDefaults(title = "Default Title", count = 10, enabled = false) { + const titleBytes = textEncoder.encode(title); + const titleId = swift.memory.retain(titleBytes); + instance.exports.bjs_testMultipleDefaults(titleId, titleBytes.length, count, enabled); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + testEnumDefault: function bjs_testEnumDefault(status = StatusValues.Active) { + const ret = instance.exports.bjs_testEnumDefault(status); + return ret; + }, + testComplexInit: function bjs_testComplexInit(greeter = new DefaultGreeter("DefaultUser")) { + const ret = instance.exports.bjs_testComplexInit(greeter.pointer); + return DefaultGreeter.__construct(ret); + }, + testEmptyInit: function bjs_testEmptyInit(greeter = new EmptyGreeter()) { + const ret = instance.exports.bjs_testEmptyInit(greeter.pointer); + return EmptyGreeter.__construct(ret); + }, + testOptionalStructDefault: function bjs_testOptionalStructDefault(point = null) { + const isSome = point != null; + let pointCleanup; + if (isSome) { + const structResult = structHelpers.Config.lower(point); + pointCleanup = structResult.cleanup; + } + i32Stack.push(+isSome); + instance.exports.bjs_testOptionalStructDefault(); + const isSome1 = i32Stack.pop(); + let optResult; + if (isSome1) { + optResult = structHelpers.Config.lift(); + } else { + optResult = null; + } + if (pointCleanup) { pointCleanup(); } + return optResult; + }, + testOptionalStructWithValueDefault: function bjs_testOptionalStructWithValueDefault(point = { name: "default", value: 42, enabled: true }) { + const isSome = point != null; + let pointCleanup; + if (isSome) { + const structResult = structHelpers.Config.lower(point); + pointCleanup = structResult.cleanup; + } + i32Stack.push(+isSome); + instance.exports.bjs_testOptionalStructWithValueDefault(); + const isSome1 = i32Stack.pop(); + let optResult; + if (isSome1) { + optResult = structHelpers.Config.lift(); + } else { + optResult = null; + } + if (pointCleanup) { pointCleanup(); } + return optResult; + }, + testIntArrayDefault: function bjs_testIntArrayDefault(values = [1, 2, 3]) { + const arrayCleanups = []; + for (const elem of values) { + i32Stack.push((elem | 0)); + } + i32Stack.push(values.length); + instance.exports.bjs_testIntArrayDefault(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.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); + i32Stack.push(bytes.length); + i32Stack.push(id); + } + i32Stack.push(names.length); + instance.exports.bjs_testStringArrayDefault(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const string = strStack.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) { + f64Stack.push(elem); + } + i32Stack.push(values.length); + instance.exports.bjs_testDoubleArrayDefault(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const f64 = f64Stack.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) { + i32Stack.push(elem ? 1 : 0); + } + i32Stack.push(flags.length); + instance.exports.bjs_testBoolArrayDefault(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const bool = i32Stack.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) { + i32Stack.push((elem | 0)); + } + i32Stack.push(items.length); + instance.exports.bjs_testEmptyArrayDefault(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.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) { + i32Stack.push((elem | 0)); + } + i32Stack.push(values.length); + instance.exports.bjs_testMixedWithArrayDefault(nameId, nameBytes.length, enabled); + const ret = tmpRetString; + tmpRetString = undefined; + 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.lift(); + return structValue; + }, + subtract: function(a, b) { + const ret = instance.exports.bjs_MathOperations_static_subtract(a, b); + return ret; + }, + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.d.ts new file mode 100644 index 000000000..dadcc74ba --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.d.ts @@ -0,0 +1,34 @@ +// 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`. + +/// 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 Box extends SwiftHeapObject { +} +export type Exports = { + Box: { + } + mirrorDictionary(values: Record): Record; + optionalDictionary(values: Record | null): Record | null; + nestedDictionary(values: Record): Record; + boxDictionary(boxes: Record): Record; + optionalBoxDictionary(boxes: Record): Record; +} +export type Imports = { + importMirrorDictionary(values: Record): Record; +} +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/DictionaryTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js new file mode 100644 index 000000000..d42fd4b2b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js @@ -0,0 +1,446 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_Box_wrap"] = function(pointer) { + const obj = _exports['Box'].__construct(pointer); + return swift.memory.retain(obj); + }; + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_importMirrorDictionary"] = function bjs_importMirrorDictionary() { + try { + const dictLen = i32Stack.pop(); + const dictResult = {}; + for (let i = 0; i < dictLen; i++) { + const f64 = f64Stack.pop(); + const string = strStack.pop(); + dictResult[string] = f64; + } + let ret = imports.importMirrorDictionary(dictResult); + const arrayCleanups = []; + const entries = Object.entries(ret); + for (const entry of entries) { + const [key, value] = entry; + const bytes = textEncoder.encode(key); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + f64Stack.push(value); + } + i32Stack.push(entries.length); + } 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 swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class Box extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Box_deinit, Box.prototype); + } + + } + const exports = { + Box, + mirrorDictionary: function bjs_mirrorDictionary(values) { + const arrayCleanups = []; + const entries = Object.entries(values); + for (const entry of entries) { + const [key, value] = entry; + const bytes = textEncoder.encode(key); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + i32Stack.push((value | 0)); + } + i32Stack.push(entries.length); + instance.exports.bjs_mirrorDictionary(); + const dictLen = i32Stack.pop(); + const dictResult = {}; + for (let i = 0; i < dictLen; i++) { + const int = i32Stack.pop(); + const string = strStack.pop(); + dictResult[string] = int; + } + for (const cleanup of arrayCleanups) { cleanup(); } + return dictResult; + }, + optionalDictionary: function bjs_optionalDictionary(values) { + const isSome = values != null; + const valuesCleanups = []; + if (isSome) { + const arrayCleanups = []; + const entries = Object.entries(values); + for (const entry of entries) { + const [key, value] = entry; + const bytes = textEncoder.encode(key); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const bytes1 = textEncoder.encode(value); + const id1 = swift.memory.retain(bytes1); + i32Stack.push(bytes1.length); + i32Stack.push(id1); + } + i32Stack.push(entries.length); + valuesCleanups.push(() => { for (const cleanup of arrayCleanups) { cleanup(); } }); + } + i32Stack.push(+isSome); + instance.exports.bjs_optionalDictionary(); + const isSome1 = i32Stack.pop(); + let optResult; + if (isSome1) { + const dictLen = i32Stack.pop(); + const dictResult = {}; + for (let i = 0; i < dictLen; i++) { + const string = strStack.pop(); + const string1 = strStack.pop(); + dictResult[string1] = string; + } + optResult = dictResult; + } else { + optResult = null; + } + for (const cleanup of valuesCleanups) { cleanup(); } + return optResult; + }, + nestedDictionary: function bjs_nestedDictionary(values) { + const arrayCleanups = []; + const entries = Object.entries(values); + for (const entry of entries) { + const [key, value] = entry; + const bytes = textEncoder.encode(key); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const arrayCleanups1 = []; + for (const elem of value) { + i32Stack.push((elem | 0)); + } + i32Stack.push(value.length); + arrayCleanups.push(() => { + for (const cleanup of arrayCleanups1) { cleanup(); } + }); + } + i32Stack.push(entries.length); + instance.exports.bjs_nestedDictionary(); + const dictLen = i32Stack.pop(); + const dictResult = {}; + for (let i = 0; i < dictLen; i++) { + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i1 = 0; i1 < arrayLen; i1++) { + const int = i32Stack.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); + const string = strStack.pop(); + dictResult[string] = arrayResult; + } + for (const cleanup of arrayCleanups) { cleanup(); } + return dictResult; + }, + boxDictionary: function bjs_boxDictionary(boxes) { + const arrayCleanups = []; + const entries = Object.entries(boxes); + for (const entry of entries) { + const [key, value] = entry; + const bytes = textEncoder.encode(key); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + ptrStack.push(value.pointer); + } + i32Stack.push(entries.length); + instance.exports.bjs_boxDictionary(); + const dictLen = i32Stack.pop(); + const dictResult = {}; + for (let i = 0; i < dictLen; i++) { + const ptr = ptrStack.pop(); + const obj = _exports['Box'].__construct(ptr); + const string = strStack.pop(); + dictResult[string] = obj; + } + for (const cleanup of arrayCleanups) { cleanup(); } + return dictResult; + }, + optionalBoxDictionary: function bjs_optionalBoxDictionary(boxes) { + const arrayCleanups = []; + const entries = Object.entries(boxes); + for (const entry of entries) { + const [key, value] = entry; + const bytes = textEncoder.encode(key); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const isSome = value != null ? 1 : 0; + if (isSome) { + ptrStack.push(value.pointer); + } else { + ptrStack.push(0); + } + i32Stack.push(isSome); + } + i32Stack.push(entries.length); + instance.exports.bjs_optionalBoxDictionary(); + const dictLen = i32Stack.pop(); + const dictResult = {}; + for (let i = 0; i < dictLen; i++) { + const isSome1 = i32Stack.pop(); + let optValue; + if (isSome1 === 0) { + optValue = null; + } else { + const ptr = ptrStack.pop(); + const obj = _exports['Box'].__construct(ptr); + optValue = obj; + } + const string = strStack.pop(); + dictResult[string] = optValue; + } + for (const cleanup of arrayCleanups) { cleanup(); } + return dictResult; + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.d.ts new file mode 100644 index 000000000..13f77ae08 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.d.ts @@ -0,0 +1,199 @@ +// 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 APIResultValues: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + readonly Flag: 2; + readonly Rate: 3; + readonly Precise: 4; + readonly Info: 5; + }; +}; + +export type APIResultTag = + { tag: typeof APIResultValues.Tag.Success; param0: string } | { tag: typeof APIResultValues.Tag.Failure; param0: number } | { tag: typeof APIResultValues.Tag.Flag; param0: boolean } | { tag: typeof APIResultValues.Tag.Rate; param0: number } | { tag: typeof APIResultValues.Tag.Precise; param0: number } | { tag: typeof APIResultValues.Tag.Info } + +export const ComplexResultValues: { + readonly Tag: { + readonly Success: 0; + readonly Error: 1; + readonly Status: 2; + readonly Coordinates: 3; + readonly Comprehensive: 4; + readonly Info: 5; + }; +}; + +export type ComplexResultTag = + { tag: typeof ComplexResultValues.Tag.Success; param0: string } | { tag: typeof ComplexResultValues.Tag.Error; param0: string; param1: number } | { tag: typeof ComplexResultValues.Tag.Status; param0: boolean; param1: number; param2: string } | { tag: typeof ComplexResultValues.Tag.Coordinates; param0: number; param1: number; param2: number } | { tag: typeof ComplexResultValues.Tag.Comprehensive; param0: boolean; param1: boolean; param2: number; param3: number; param4: number; param5: number; param6: string; param7: string; param8: string } | { tag: typeof ComplexResultValues.Tag.Info } + +export const APIOptionalResultValues: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + readonly Status: 2; + }; +}; + +export type APIOptionalResultTag = + { tag: typeof APIOptionalResultValues.Tag.Success; param0: string | null } | { tag: typeof APIOptionalResultValues.Tag.Failure; param0: number | null; param1: boolean | null } | { tag: typeof APIOptionalResultValues.Tag.Status; param0: boolean | null; param1: number | null; param2: string | null } + +export const PrecisionValues: { + readonly Rough: 0.1; + readonly Fine: 0.001; +}; +export type PrecisionTag = typeof PrecisionValues[keyof typeof PrecisionValues]; + +export const CardinalDirectionValues: { + readonly North: 0; + readonly South: 1; + readonly East: 2; + readonly West: 3; +}; +export type CardinalDirectionTag = typeof CardinalDirectionValues[keyof typeof CardinalDirectionValues]; + +export const TypedPayloadResultValues: { + readonly Tag: { + readonly Precision: 0; + readonly Direction: 1; + readonly OptPrecision: 2; + readonly OptDirection: 3; + readonly Empty: 4; + }; +}; + +export type TypedPayloadResultTag = + { tag: typeof TypedPayloadResultValues.Tag.Precision; param0: PrecisionTag } | { tag: typeof TypedPayloadResultValues.Tag.Direction; param0: CardinalDirectionTag } | { tag: typeof TypedPayloadResultValues.Tag.OptPrecision; param0: PrecisionTag | null } | { tag: typeof TypedPayloadResultValues.Tag.OptDirection; param0: CardinalDirectionTag | null } | { tag: typeof TypedPayloadResultValues.Tag.Empty } + +export const AllTypesResultValues: { + readonly Tag: { + readonly StructPayload: 0; + readonly ClassPayload: 1; + readonly JsObjectPayload: 2; + readonly NestedEnum: 3; + readonly ArrayPayload: 4; + readonly Empty: 5; + }; +}; + +export type AllTypesResultTag = + { tag: typeof AllTypesResultValues.Tag.StructPayload; param0: Point } | { tag: typeof AllTypesResultValues.Tag.ClassPayload; param0: User } | { tag: typeof AllTypesResultValues.Tag.JsObjectPayload; param0: any } | { tag: typeof AllTypesResultValues.Tag.NestedEnum; param0: APIResultTag } | { tag: typeof AllTypesResultValues.Tag.ArrayPayload; param0: number[] } | { tag: typeof AllTypesResultValues.Tag.Empty } + +export const OptionalAllTypesResultValues: { + readonly Tag: { + readonly OptStruct: 0; + readonly OptClass: 1; + readonly OptJSObject: 2; + readonly OptNestedEnum: 3; + readonly OptArray: 4; + readonly Empty: 5; + }; +}; + +export type OptionalAllTypesResultTag = + { tag: typeof OptionalAllTypesResultValues.Tag.OptStruct; param0: Point | null } | { tag: typeof OptionalAllTypesResultValues.Tag.OptClass; param0: User | null } | { tag: typeof OptionalAllTypesResultValues.Tag.OptJSObject; param0: any | null } | { tag: typeof OptionalAllTypesResultValues.Tag.OptNestedEnum; param0: APIResultTag | null } | { tag: typeof OptionalAllTypesResultValues.Tag.OptArray; param0: number[] | null } | { tag: typeof OptionalAllTypesResultValues.Tag.Empty } + +export interface Point { + x: number; + y: number; +} +export type APIResultObject = typeof APIResultValues; + +export type ComplexResultObject = typeof ComplexResultValues; + +export type ResultObject = typeof Utilities.ResultValues; + +export type NetworkingResultObject = typeof API.NetworkingResultValues; + +export type APIOptionalResultObject = typeof APIOptionalResultValues; + +export type PrecisionObject = typeof PrecisionValues; + +export type CardinalDirectionObject = typeof CardinalDirectionValues; + +export type TypedPayloadResultObject = typeof TypedPayloadResultValues; + +export type AllTypesResultObject = typeof AllTypesResultValues; + +export type OptionalAllTypesResultObject = typeof OptionalAllTypesResultValues; + +export namespace API { + const NetworkingResultValues: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + }; + }; + type NetworkingResultTag = + { tag: typeof NetworkingResultValues.Tag.Success; param0: string } | { tag: typeof NetworkingResultValues.Tag.Failure; param0: string; param1: number } +} +export namespace Utilities { + const ResultValues: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + readonly Status: 2; + }; + }; + type ResultTag = + { tag: typeof ResultValues.Tag.Success; param0: string } | { tag: typeof ResultValues.Tag.Failure; param0: string; param1: number } | { tag: typeof ResultValues.Tag.Status; param0: boolean; param1: number; param2: string } +} +/// 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 User extends SwiftHeapObject { +} +export type Exports = { + User: { + } + handle(result: APIResultTag): void; + getResult(): APIResultTag; + roundtripAPIResult(result: APIResultTag): APIResultTag; + roundTripOptionalAPIResult(result: APIResultTag | null): APIResultTag | null; + handleComplex(result: ComplexResultTag): void; + getComplexResult(): ComplexResultTag; + roundtripComplexResult(result: ComplexResultTag): ComplexResultTag; + roundTripOptionalComplexResult(result: ComplexResultTag | null): ComplexResultTag | null; + roundTripOptionalUtilitiesResult(result: Utilities.ResultTag | null): Utilities.ResultTag | null; + roundTripOptionalNetworkingResult(result: API.NetworkingResultTag | null): API.NetworkingResultTag | null; + roundTripOptionalAPIOptionalResult(result: APIOptionalResultTag | null): APIOptionalResultTag | null; + compareAPIResults(result1: APIOptionalResultTag | null, result2: APIOptionalResultTag | null): APIOptionalResultTag | null; + roundTripTypedPayloadResult(result: TypedPayloadResultTag): TypedPayloadResultTag; + roundTripOptionalTypedPayloadResult(result: TypedPayloadResultTag | null): TypedPayloadResultTag | null; + roundTripAllTypesResult(result: AllTypesResultTag): AllTypesResultTag; + roundTripOptionalAllTypesResult(result: AllTypesResultTag | null): AllTypesResultTag | null; + roundTripOptionalPayloadResult(result: OptionalAllTypesResultTag): OptionalAllTypesResultTag; + roundTripOptionalPayloadResultOpt(result: OptionalAllTypesResultTag | null): OptionalAllTypesResultTag | null; + APIResult: APIResultObject + ComplexResult: ComplexResultObject + APIOptionalResult: APIOptionalResultObject + Precision: PrecisionObject + CardinalDirection: CardinalDirectionObject + TypedPayloadResult: TypedPayloadResultObject + AllTypesResult: AllTypesResultObject + OptionalAllTypesResult: OptionalAllTypesResultObject + API: { + NetworkingResult: NetworkingResultObject + }, + Utilities: { + Result: ResultObject + }, +} +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/EnumAssociatedValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js new file mode 100644 index 000000000..2d2c6924b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js @@ -0,0 +1,1371 @@ +// 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 APIResultValues = { + Tag: { + Success: 0, + Failure: 1, + Flag: 2, + Rate: 3, + Precise: 4, + Info: 5, + }, +}; +export const ComplexResultValues = { + Tag: { + Success: 0, + Error: 1, + Status: 2, + Coordinates: 3, + Comprehensive: 4, + Info: 5, + }, +}; +export const ResultValues = { + Tag: { + Success: 0, + Failure: 1, + Status: 2, + }, +}; +export const NetworkingResultValues = { + Tag: { + Success: 0, + Failure: 1, + }, +}; +export const APIOptionalResultValues = { + Tag: { + Success: 0, + Failure: 1, + Status: 2, + }, +}; +export const PrecisionValues = { + Rough: 0.1, + Fine: 0.001, +}; + +export const CardinalDirectionValues = { + North: 0, + South: 1, + East: 2, + West: 3, +}; + +export const TypedPayloadResultValues = { + Tag: { + Precision: 0, + Direction: 1, + OptPrecision: 2, + OptDirection: 3, + Empty: 4, + }, +}; +export const AllTypesResultValues = { + Tag: { + StructPayload: 0, + ClassPayload: 1, + JsObjectPayload: 2, + NestedEnum: 3, + ArrayPayload: 4, + Empty: 5, + }, +}; +export const OptionalAllTypesResultValues = { + Tag: { + OptStruct: 0, + OptClass: 1, + OptJSObject: 2, + OptNestedEnum: 3, + OptArray: 4, + Empty: 5, + }, +}; +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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createPointHelpers = () => { + return () => ({ + lower: (value) => { + f64Stack.push(value.x); + f64Stack.push(value.y); + return { cleanup: undefined }; + }, + lift: () => { + const f64 = f64Stack.pop(); + const f641 = f64Stack.pop(); + return { x: f641, y: f64 }; + } + }); + }; + const __bjs_createAPIResultValuesHelpers = () => { + return () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case APIResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Success, cleanup }; + } + case APIResultValues.Tag.Failure: { + i32Stack.push((value.param0 | 0)); + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Failure, cleanup }; + } + case APIResultValues.Tag.Flag: { + i32Stack.push(value.param0 ? 1 : 0); + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Flag, cleanup }; + } + case APIResultValues.Tag.Rate: { + f32Stack.push(Math.fround(value.param0)); + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Rate, cleanup }; + } + case APIResultValues.Tag.Precise: { + f64Stack.push(value.param0); + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Precise, cleanup }; + } + case APIResultValues.Tag.Info: { + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Info, cleanup }; + } + default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case APIResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: APIResultValues.Tag.Success, param0: string }; + } + case APIResultValues.Tag.Failure: { + const int = i32Stack.pop(); + return { tag: APIResultValues.Tag.Failure, param0: int }; + } + case APIResultValues.Tag.Flag: { + const bool = i32Stack.pop() !== 0; + return { tag: APIResultValues.Tag.Flag, param0: bool }; + } + case APIResultValues.Tag.Rate: { + const f32 = f32Stack.pop(); + return { tag: APIResultValues.Tag.Rate, param0: f32 }; + } + case APIResultValues.Tag.Precise: { + const f64 = f64Stack.pop(); + return { tag: APIResultValues.Tag.Precise, param0: f64 }; + } + case APIResultValues.Tag.Info: return { tag: APIResultValues.Tag.Info }; + default: throw new Error("Unknown APIResultValues tag returned from Swift: " + String(tag)); + } + } + }); + }; + const __bjs_createComplexResultValuesHelpers = () => { + return () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case ComplexResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const cleanup = undefined; + return { caseId: ComplexResultValues.Tag.Success, cleanup }; + } + case ComplexResultValues.Tag.Error: { + i32Stack.push((value.param1 | 0)); + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const cleanup = undefined; + return { caseId: ComplexResultValues.Tag.Error, cleanup }; + } + case ComplexResultValues.Tag.Status: { + const bytes = textEncoder.encode(value.param2); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + i32Stack.push((value.param1 | 0)); + i32Stack.push(value.param0 ? 1 : 0); + const cleanup = undefined; + return { caseId: ComplexResultValues.Tag.Status, cleanup }; + } + case ComplexResultValues.Tag.Coordinates: { + f64Stack.push(value.param2); + f64Stack.push(value.param1); + f64Stack.push(value.param0); + const cleanup = undefined; + return { caseId: ComplexResultValues.Tag.Coordinates, cleanup }; + } + case ComplexResultValues.Tag.Comprehensive: { + const bytes = textEncoder.encode(value.param8); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const bytes1 = textEncoder.encode(value.param7); + const id1 = swift.memory.retain(bytes1); + i32Stack.push(bytes1.length); + i32Stack.push(id1); + const bytes2 = textEncoder.encode(value.param6); + const id2 = swift.memory.retain(bytes2); + i32Stack.push(bytes2.length); + i32Stack.push(id2); + f64Stack.push(value.param5); + f64Stack.push(value.param4); + i32Stack.push((value.param3 | 0)); + i32Stack.push((value.param2 | 0)); + i32Stack.push(value.param1 ? 1 : 0); + i32Stack.push(value.param0 ? 1 : 0); + const cleanup = undefined; + return { caseId: ComplexResultValues.Tag.Comprehensive, cleanup }; + } + case ComplexResultValues.Tag.Info: { + const cleanup = undefined; + return { caseId: ComplexResultValues.Tag.Info, cleanup }; + } + default: throw new Error("Unknown ComplexResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case ComplexResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: ComplexResultValues.Tag.Success, param0: string }; + } + case ComplexResultValues.Tag.Error: { + const int = i32Stack.pop(); + const string = strStack.pop(); + return { tag: ComplexResultValues.Tag.Error, param0: string, param1: int }; + } + case ComplexResultValues.Tag.Status: { + const string = strStack.pop(); + const int = i32Stack.pop(); + const bool = i32Stack.pop() !== 0; + return { tag: ComplexResultValues.Tag.Status, param0: bool, param1: int, param2: string }; + } + case ComplexResultValues.Tag.Coordinates: { + const f64 = f64Stack.pop(); + const f641 = f64Stack.pop(); + const f642 = f64Stack.pop(); + return { tag: ComplexResultValues.Tag.Coordinates, param0: f642, param1: f641, param2: f64 }; + } + case ComplexResultValues.Tag.Comprehensive: { + const string = strStack.pop(); + const string1 = strStack.pop(); + const string2 = strStack.pop(); + const f64 = f64Stack.pop(); + const f641 = f64Stack.pop(); + const int = i32Stack.pop(); + const int1 = i32Stack.pop(); + const bool = i32Stack.pop() !== 0; + const bool1 = i32Stack.pop() !== 0; + return { tag: ComplexResultValues.Tag.Comprehensive, param0: bool1, param1: bool, param2: int1, param3: int, param4: f641, param5: f64, param6: string2, param7: string1, param8: string }; + } + case ComplexResultValues.Tag.Info: return { tag: ComplexResultValues.Tag.Info }; + default: throw new Error("Unknown ComplexResultValues tag returned from Swift: " + String(tag)); + } + } + }); + }; + const __bjs_createResultValuesHelpers = () => { + return () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case ResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const cleanup = undefined; + return { caseId: ResultValues.Tag.Success, cleanup }; + } + case ResultValues.Tag.Failure: { + i32Stack.push((value.param1 | 0)); + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const cleanup = undefined; + return { caseId: ResultValues.Tag.Failure, cleanup }; + } + case ResultValues.Tag.Status: { + const bytes = textEncoder.encode(value.param2); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + i32Stack.push((value.param1 | 0)); + i32Stack.push(value.param0 ? 1 : 0); + const cleanup = undefined; + return { caseId: ResultValues.Tag.Status, cleanup }; + } + default: throw new Error("Unknown ResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case ResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: ResultValues.Tag.Success, param0: string }; + } + case ResultValues.Tag.Failure: { + const int = i32Stack.pop(); + const string = strStack.pop(); + return { tag: ResultValues.Tag.Failure, param0: string, param1: int }; + } + case ResultValues.Tag.Status: { + const string = strStack.pop(); + const int = i32Stack.pop(); + const bool = i32Stack.pop() !== 0; + return { tag: ResultValues.Tag.Status, param0: bool, param1: int, param2: string }; + } + default: throw new Error("Unknown ResultValues tag returned from Swift: " + String(tag)); + } + } + }); + }; + const __bjs_createNetworkingResultValuesHelpers = () => { + return () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case NetworkingResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const cleanup = undefined; + return { caseId: NetworkingResultValues.Tag.Success, cleanup }; + } + case NetworkingResultValues.Tag.Failure: { + i32Stack.push((value.param1 | 0)); + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const cleanup = undefined; + return { caseId: NetworkingResultValues.Tag.Failure, cleanup }; + } + default: throw new Error("Unknown NetworkingResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case NetworkingResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: NetworkingResultValues.Tag.Success, param0: string }; + } + case NetworkingResultValues.Tag.Failure: { + const int = i32Stack.pop(); + const string = strStack.pop(); + return { tag: NetworkingResultValues.Tag.Failure, param0: string, param1: int }; + } + default: throw new Error("Unknown NetworkingResultValues tag returned from Swift: " + String(tag)); + } + } + }); + }; + const __bjs_createAPIOptionalResultValuesHelpers = () => { + return () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case APIOptionalResultValues.Tag.Success: { + const isSome = value.param0 != null; + let id; + if (isSome) { + let bytes = textEncoder.encode(value.param0); + id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + } else { + i32Stack.push(0); + i32Stack.push(0); + } + i32Stack.push(isSome ? 1 : 0); + const cleanup = undefined; + return { caseId: APIOptionalResultValues.Tag.Success, cleanup }; + } + case APIOptionalResultValues.Tag.Failure: { + const isSome = value.param1 != null; + i32Stack.push(isSome ? (value.param1 ? 1 : 0) : 0); + i32Stack.push(isSome ? 1 : 0); + const isSome1 = value.param0 != null; + i32Stack.push(isSome1 ? (value.param0 | 0) : 0); + i32Stack.push(isSome1 ? 1 : 0); + const cleanup = undefined; + return { caseId: APIOptionalResultValues.Tag.Failure, cleanup }; + } + case APIOptionalResultValues.Tag.Status: { + const isSome = value.param2 != null; + let id; + if (isSome) { + let bytes = textEncoder.encode(value.param2); + id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + } else { + i32Stack.push(0); + i32Stack.push(0); + } + i32Stack.push(isSome ? 1 : 0); + const isSome1 = value.param1 != null; + i32Stack.push(isSome1 ? (value.param1 | 0) : 0); + i32Stack.push(isSome1 ? 1 : 0); + const isSome2 = value.param0 != null; + i32Stack.push(isSome2 ? (value.param0 ? 1 : 0) : 0); + i32Stack.push(isSome2 ? 1 : 0); + const cleanup = undefined; + return { caseId: APIOptionalResultValues.Tag.Status, cleanup }; + } + default: throw new Error("Unknown APIOptionalResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case APIOptionalResultValues.Tag.Success: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const string = strStack.pop(); + optional = string; + } else { + optional = null; + } + return { tag: APIOptionalResultValues.Tag.Success, param0: optional }; + } + case APIOptionalResultValues.Tag.Failure: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const bool = i32Stack.pop() !== 0; + optional = bool; + } else { + optional = null; + } + const isSome1 = i32Stack.pop(); + let optional1; + if (isSome1) { + const int = i32Stack.pop(); + optional1 = int; + } else { + optional1 = null; + } + return { tag: APIOptionalResultValues.Tag.Failure, param0: optional1, param1: optional }; + } + case APIOptionalResultValues.Tag.Status: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const string = strStack.pop(); + optional = string; + } else { + optional = null; + } + const isSome1 = i32Stack.pop(); + let optional1; + if (isSome1) { + const int = i32Stack.pop(); + optional1 = int; + } else { + optional1 = null; + } + const isSome2 = i32Stack.pop(); + let optional2; + if (isSome2) { + const bool = i32Stack.pop() !== 0; + optional2 = bool; + } else { + optional2 = null; + } + return { tag: APIOptionalResultValues.Tag.Status, param0: optional2, param1: optional1, param2: optional }; + } + default: throw new Error("Unknown APIOptionalResultValues tag returned from Swift: " + String(tag)); + } + } + }); + }; + const __bjs_createTypedPayloadResultValuesHelpers = () => { + return () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case TypedPayloadResultValues.Tag.Precision: { + f32Stack.push(Math.fround(value.param0)); + const cleanup = undefined; + return { caseId: TypedPayloadResultValues.Tag.Precision, cleanup }; + } + case TypedPayloadResultValues.Tag.Direction: { + i32Stack.push((value.param0 | 0)); + const cleanup = undefined; + return { caseId: TypedPayloadResultValues.Tag.Direction, cleanup }; + } + case TypedPayloadResultValues.Tag.OptPrecision: { + const isSome = value.param0 != null; + f32Stack.push(isSome ? Math.fround(value.param0) : 0.0); + i32Stack.push(isSome ? 1 : 0); + const cleanup = undefined; + return { caseId: TypedPayloadResultValues.Tag.OptPrecision, cleanup }; + } + case TypedPayloadResultValues.Tag.OptDirection: { + const isSome = value.param0 != null; + i32Stack.push(isSome ? (value.param0 | 0) : 0); + i32Stack.push(isSome ? 1 : 0); + const cleanup = undefined; + return { caseId: TypedPayloadResultValues.Tag.OptDirection, cleanup }; + } + case TypedPayloadResultValues.Tag.Empty: { + const cleanup = undefined; + return { caseId: TypedPayloadResultValues.Tag.Empty, cleanup }; + } + default: throw new Error("Unknown TypedPayloadResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case TypedPayloadResultValues.Tag.Precision: { + const rawValue = f32Stack.pop(); + return { tag: TypedPayloadResultValues.Tag.Precision, param0: rawValue }; + } + case TypedPayloadResultValues.Tag.Direction: { + const caseId = i32Stack.pop(); + return { tag: TypedPayloadResultValues.Tag.Direction, param0: caseId }; + } + case TypedPayloadResultValues.Tag.OptPrecision: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const rawValue = f32Stack.pop(); + optional = rawValue; + } else { + optional = null; + } + return { tag: TypedPayloadResultValues.Tag.OptPrecision, param0: optional }; + } + case TypedPayloadResultValues.Tag.OptDirection: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const caseId = i32Stack.pop(); + optional = caseId; + } else { + optional = null; + } + return { tag: TypedPayloadResultValues.Tag.OptDirection, param0: optional }; + } + case TypedPayloadResultValues.Tag.Empty: return { tag: TypedPayloadResultValues.Tag.Empty }; + default: throw new Error("Unknown TypedPayloadResultValues tag returned from Swift: " + String(tag)); + } + } + }); + }; + const __bjs_createAllTypesResultValuesHelpers = () => { + return () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case AllTypesResultValues.Tag.StructPayload: { + const { cleanup: structCleanup } = structHelpers.Point.lower(value.param0); + const cleanup = () => { + if (structCleanup) { structCleanup(); } + }; + return { caseId: AllTypesResultValues.Tag.StructPayload, cleanup }; + } + case AllTypesResultValues.Tag.ClassPayload: { + ptrStack.push(value.param0.pointer); + const cleanup = undefined; + return { caseId: AllTypesResultValues.Tag.ClassPayload, cleanup }; + } + case AllTypesResultValues.Tag.JsObjectPayload: { + const objId = swift.memory.retain(value.param0); + i32Stack.push(objId); + const cleanup = undefined; + return { caseId: AllTypesResultValues.Tag.JsObjectPayload, cleanup }; + } + case AllTypesResultValues.Tag.NestedEnum: { + const { caseId: caseId, cleanup: enumCleanup } = enumHelpers.APIResult.lower(value.param0); + i32Stack.push(caseId); + const cleanup = () => { + if (enumCleanup) { enumCleanup(); } + }; + return { caseId: AllTypesResultValues.Tag.NestedEnum, cleanup }; + } + case AllTypesResultValues.Tag.ArrayPayload: { + const arrayCleanups = []; + for (const elem of value.param0) { + i32Stack.push((elem | 0)); + } + i32Stack.push(value.param0.length); + const cleanup = () => { + for (const cleanup of arrayCleanups) { cleanup(); } + }; + return { caseId: AllTypesResultValues.Tag.ArrayPayload, cleanup }; + } + case AllTypesResultValues.Tag.Empty: { + const cleanup = undefined; + return { caseId: AllTypesResultValues.Tag.Empty, cleanup }; + } + default: throw new Error("Unknown AllTypesResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case AllTypesResultValues.Tag.StructPayload: { + const struct = structHelpers.Point.lift(); + return { tag: AllTypesResultValues.Tag.StructPayload, param0: struct }; + } + case AllTypesResultValues.Tag.ClassPayload: { + const ptr = ptrStack.pop(); + const obj = _exports['User'].__construct(ptr); + return { tag: AllTypesResultValues.Tag.ClassPayload, param0: obj }; + } + case AllTypesResultValues.Tag.JsObjectPayload: { + const objId = i32Stack.pop(); + const obj = swift.memory.getObject(objId); + swift.memory.release(objId); + return { tag: AllTypesResultValues.Tag.JsObjectPayload, param0: obj }; + } + case AllTypesResultValues.Tag.NestedEnum: { + const enumValue = enumHelpers.APIResult.lift(i32Stack.pop(), ); + return { tag: AllTypesResultValues.Tag.NestedEnum, param0: enumValue }; + } + case AllTypesResultValues.Tag.ArrayPayload: { + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); + return { tag: AllTypesResultValues.Tag.ArrayPayload, param0: arrayResult }; + } + case AllTypesResultValues.Tag.Empty: return { tag: AllTypesResultValues.Tag.Empty }; + default: throw new Error("Unknown AllTypesResultValues tag returned from Swift: " + String(tag)); + } + } + }); + }; + const __bjs_createOptionalAllTypesResultValuesHelpers = () => { + return () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case OptionalAllTypesResultValues.Tag.OptStruct: { + const isSome = value.param0 != null; + let nestedCleanup; + if (isSome) { + const structResult = structHelpers.Point.lower(value.param0); + nestedCleanup = structResult.cleanup; + } + i32Stack.push(isSome ? 1 : 0); + const cleanup = () => { + if (nestedCleanup) { nestedCleanup(); } + }; + return { caseId: OptionalAllTypesResultValues.Tag.OptStruct, cleanup }; + } + case OptionalAllTypesResultValues.Tag.OptClass: { + const isSome = value.param0 != null; + if (isSome) { + ptrStack.push(value.param0.pointer); + } else { + ptrStack.push(0); + } + i32Stack.push(isSome ? 1 : 0); + const cleanup = undefined; + return { caseId: OptionalAllTypesResultValues.Tag.OptClass, cleanup }; + } + case OptionalAllTypesResultValues.Tag.OptJSObject: { + const isSome = value.param0 != null; + let id; + if (isSome) { + id = swift.memory.retain(value.param0); + i32Stack.push(id); + } else { + id = undefined; + i32Stack.push(0); + } + i32Stack.push(isSome ? 1 : 0); + const cleanup = undefined; + return { caseId: OptionalAllTypesResultValues.Tag.OptJSObject, cleanup }; + } + case OptionalAllTypesResultValues.Tag.OptNestedEnum: { + const isSome = value.param0 != null; + let enumCaseId, enumCleanup; + if (isSome) { + const enumResult = enumHelpers.APIResult.lower(value.param0); + enumCaseId = enumResult.caseId; + enumCleanup = enumResult.cleanup; + i32Stack.push(enumCaseId); + } else { + i32Stack.push(0); + } + i32Stack.push(isSome ? 1 : 0); + const cleanup = () => { + if (enumCleanup) { enumCleanup(); } + }; + return { caseId: OptionalAllTypesResultValues.Tag.OptNestedEnum, cleanup }; + } + case OptionalAllTypesResultValues.Tag.OptArray: { + const isSome = value.param0 != null; + let arrCleanup; + if (isSome) { + const arrayCleanups = []; + for (const elem of value.param0) { + i32Stack.push((elem | 0)); + } + i32Stack.push(value.param0.length); + arrCleanup = () => { + for (const cleanup of arrayCleanups) { cleanup(); } + }; + } + i32Stack.push(isSome ? 1 : 0); + const cleanup = () => { + if (arrCleanup) { arrCleanup(); } + }; + return { caseId: OptionalAllTypesResultValues.Tag.OptArray, cleanup }; + } + case OptionalAllTypesResultValues.Tag.Empty: { + const cleanup = undefined; + return { caseId: OptionalAllTypesResultValues.Tag.Empty, cleanup }; + } + default: throw new Error("Unknown OptionalAllTypesResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case OptionalAllTypesResultValues.Tag.OptStruct: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const struct = structHelpers.Point.lift(); + optional = struct; + } else { + optional = null; + } + return { tag: OptionalAllTypesResultValues.Tag.OptStruct, param0: optional }; + } + case OptionalAllTypesResultValues.Tag.OptClass: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const ptr = ptrStack.pop(); + const obj = _exports['User'].__construct(ptr); + optional = obj; + } else { + optional = null; + } + return { tag: OptionalAllTypesResultValues.Tag.OptClass, param0: optional }; + } + case OptionalAllTypesResultValues.Tag.OptJSObject: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const objId = i32Stack.pop(); + const obj = swift.memory.getObject(objId); + swift.memory.release(objId); + optional = obj; + } else { + optional = null; + } + return { tag: OptionalAllTypesResultValues.Tag.OptJSObject, param0: optional }; + } + case OptionalAllTypesResultValues.Tag.OptNestedEnum: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const caseId = i32Stack.pop(); + optional = enumHelpers.APIResult.lift(caseId); + } else { + optional = null; + } + return { tag: OptionalAllTypesResultValues.Tag.OptNestedEnum, param0: optional }; + } + case OptionalAllTypesResultValues.Tag.OptArray: { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); + optional = arrayResult; + } else { + optional = null; + } + return { tag: OptionalAllTypesResultValues.Tag.OptArray, param0: optional }; + } + case OptionalAllTypesResultValues.Tag.Empty: return { tag: OptionalAllTypesResultValues.Tag.Empty }; + default: throw new Error("Unknown OptionalAllTypesResultValues tag returned from Swift: " + String(tag)); + } + } + }); + }; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_struct_lower_Point"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.Point.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_Point"] = function() { + const value = structHelpers.Point.lift(); + 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_User_wrap"] = function(pointer) { + const obj = _exports['User'].__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; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class User extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_User_deinit, User.prototype); + } + + } + const PointHelpers = __bjs_createPointHelpers()(); + structHelpers.Point = PointHelpers; + + const APIResultHelpers = __bjs_createAPIResultValuesHelpers()(); + enumHelpers.APIResult = APIResultHelpers; + + const ComplexResultHelpers = __bjs_createComplexResultValuesHelpers()(); + enumHelpers.ComplexResult = ComplexResultHelpers; + + const ResultHelpers = __bjs_createResultValuesHelpers()(); + enumHelpers.Result = ResultHelpers; + + const NetworkingResultHelpers = __bjs_createNetworkingResultValuesHelpers()(); + enumHelpers.NetworkingResult = NetworkingResultHelpers; + + const APIOptionalResultHelpers = __bjs_createAPIOptionalResultValuesHelpers()(); + enumHelpers.APIOptionalResult = APIOptionalResultHelpers; + + const TypedPayloadResultHelpers = __bjs_createTypedPayloadResultValuesHelpers()(); + enumHelpers.TypedPayloadResult = TypedPayloadResultHelpers; + + const AllTypesResultHelpers = __bjs_createAllTypesResultValuesHelpers()(); + enumHelpers.AllTypesResult = AllTypesResultHelpers; + + const OptionalAllTypesResultHelpers = __bjs_createOptionalAllTypesResultValuesHelpers()(); + enumHelpers.OptionalAllTypesResult = OptionalAllTypesResultHelpers; + + const exports = { + User, + handle: function bjs_handle(result) { + const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.APIResult.lower(result); + instance.exports.bjs_handle(resultCaseId); + if (resultCleanup) { resultCleanup(); } + }, + getResult: function bjs_getResult() { + instance.exports.bjs_getResult(); + const ret = enumHelpers.APIResult.lift(i32Stack.pop()); + return ret; + }, + roundtripAPIResult: function bjs_roundtripAPIResult(result) { + const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.APIResult.lower(result); + instance.exports.bjs_roundtripAPIResult(resultCaseId); + const ret = enumHelpers.APIResult.lift(i32Stack.pop()); + if (resultCleanup) { resultCleanup(); } + return ret; + }, + roundTripOptionalAPIResult: function bjs_roundTripOptionalAPIResult(result) { + const isSome = result != null; + let resultCaseId, resultCleanup; + if (isSome) { + const enumResult = enumHelpers.APIResult.lower(result); + resultCaseId = enumResult.caseId; + resultCleanup = enumResult.cleanup; + } + instance.exports.bjs_roundTripOptionalAPIResult(+isSome, isSome ? resultCaseId : 0); + const tag = i32Stack.pop(); + const isNull = (tag === -1); + let optResult; + if (isNull) { + optResult = null; + } else { + optResult = enumHelpers.APIResult.lift(tag); + } + if (resultCleanup) { resultCleanup(); } + return optResult; + }, + handleComplex: function bjs_handleComplex(result) { + const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.ComplexResult.lower(result); + instance.exports.bjs_handleComplex(resultCaseId); + if (resultCleanup) { resultCleanup(); } + }, + getComplexResult: function bjs_getComplexResult() { + instance.exports.bjs_getComplexResult(); + const ret = enumHelpers.ComplexResult.lift(i32Stack.pop()); + return ret; + }, + roundtripComplexResult: function bjs_roundtripComplexResult(result) { + const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.ComplexResult.lower(result); + instance.exports.bjs_roundtripComplexResult(resultCaseId); + const ret = enumHelpers.ComplexResult.lift(i32Stack.pop()); + if (resultCleanup) { resultCleanup(); } + return ret; + }, + roundTripOptionalComplexResult: function bjs_roundTripOptionalComplexResult(result) { + const isSome = result != null; + let resultCaseId, resultCleanup; + if (isSome) { + const enumResult = enumHelpers.ComplexResult.lower(result); + resultCaseId = enumResult.caseId; + resultCleanup = enumResult.cleanup; + } + instance.exports.bjs_roundTripOptionalComplexResult(+isSome, isSome ? resultCaseId : 0); + const tag = i32Stack.pop(); + const isNull = (tag === -1); + let optResult; + if (isNull) { + optResult = null; + } else { + optResult = enumHelpers.ComplexResult.lift(tag); + } + if (resultCleanup) { resultCleanup(); } + return optResult; + }, + roundTripOptionalUtilitiesResult: function bjs_roundTripOptionalUtilitiesResult(result) { + const isSome = result != null; + let resultCaseId, resultCleanup; + if (isSome) { + const enumResult = enumHelpers.Result.lower(result); + resultCaseId = enumResult.caseId; + resultCleanup = enumResult.cleanup; + } + instance.exports.bjs_roundTripOptionalUtilitiesResult(+isSome, isSome ? resultCaseId : 0); + const tag = i32Stack.pop(); + const isNull = (tag === -1); + let optResult; + if (isNull) { + optResult = null; + } else { + optResult = enumHelpers.Result.lift(tag); + } + if (resultCleanup) { resultCleanup(); } + return optResult; + }, + roundTripOptionalNetworkingResult: function bjs_roundTripOptionalNetworkingResult(result) { + const isSome = result != null; + let resultCaseId, resultCleanup; + if (isSome) { + const enumResult = enumHelpers.NetworkingResult.lower(result); + resultCaseId = enumResult.caseId; + resultCleanup = enumResult.cleanup; + } + instance.exports.bjs_roundTripOptionalNetworkingResult(+isSome, isSome ? resultCaseId : 0); + const tag = i32Stack.pop(); + const isNull = (tag === -1); + let optResult; + if (isNull) { + optResult = null; + } else { + optResult = enumHelpers.NetworkingResult.lift(tag); + } + if (resultCleanup) { resultCleanup(); } + return optResult; + }, + roundTripOptionalAPIOptionalResult: function bjs_roundTripOptionalAPIOptionalResult(result) { + const isSome = result != null; + let resultCaseId, resultCleanup; + if (isSome) { + const enumResult = enumHelpers.APIOptionalResult.lower(result); + resultCaseId = enumResult.caseId; + resultCleanup = enumResult.cleanup; + } + instance.exports.bjs_roundTripOptionalAPIOptionalResult(+isSome, isSome ? resultCaseId : 0); + const tag = i32Stack.pop(); + const isNull = (tag === -1); + let optResult; + if (isNull) { + optResult = null; + } else { + optResult = enumHelpers.APIOptionalResult.lift(tag); + } + if (resultCleanup) { resultCleanup(); } + return optResult; + }, + compareAPIResults: function bjs_compareAPIResults(result1, result2) { + const isSome = result1 != null; + let result1CaseId, result1Cleanup; + if (isSome) { + const enumResult = enumHelpers.APIOptionalResult.lower(result1); + result1CaseId = enumResult.caseId; + result1Cleanup = enumResult.cleanup; + } + const isSome1 = result2 != null; + let result2CaseId, result2Cleanup; + if (isSome1) { + const enumResult1 = enumHelpers.APIOptionalResult.lower(result2); + result2CaseId = enumResult1.caseId; + result2Cleanup = enumResult1.cleanup; + } + instance.exports.bjs_compareAPIResults(+isSome, isSome ? result1CaseId : 0, +isSome1, isSome1 ? result2CaseId : 0); + const tag = i32Stack.pop(); + const isNull = (tag === -1); + let optResult; + if (isNull) { + optResult = null; + } else { + optResult = enumHelpers.APIOptionalResult.lift(tag); + } + if (result1Cleanup) { result1Cleanup(); } + if (result2Cleanup) { result2Cleanup(); } + return optResult; + }, + roundTripTypedPayloadResult: function bjs_roundTripTypedPayloadResult(result) { + const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.TypedPayloadResult.lower(result); + instance.exports.bjs_roundTripTypedPayloadResult(resultCaseId); + const ret = enumHelpers.TypedPayloadResult.lift(i32Stack.pop()); + if (resultCleanup) { resultCleanup(); } + return ret; + }, + roundTripOptionalTypedPayloadResult: function bjs_roundTripOptionalTypedPayloadResult(result) { + const isSome = result != null; + let resultCaseId, resultCleanup; + if (isSome) { + const enumResult = enumHelpers.TypedPayloadResult.lower(result); + resultCaseId = enumResult.caseId; + resultCleanup = enumResult.cleanup; + } + instance.exports.bjs_roundTripOptionalTypedPayloadResult(+isSome, isSome ? resultCaseId : 0); + const tag = i32Stack.pop(); + const isNull = (tag === -1); + let optResult; + if (isNull) { + optResult = null; + } else { + optResult = enumHelpers.TypedPayloadResult.lift(tag); + } + if (resultCleanup) { resultCleanup(); } + return optResult; + }, + roundTripAllTypesResult: function bjs_roundTripAllTypesResult(result) { + const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.AllTypesResult.lower(result); + instance.exports.bjs_roundTripAllTypesResult(resultCaseId); + const ret = enumHelpers.AllTypesResult.lift(i32Stack.pop()); + if (resultCleanup) { resultCleanup(); } + return ret; + }, + roundTripOptionalAllTypesResult: function bjs_roundTripOptionalAllTypesResult(result) { + const isSome = result != null; + let resultCaseId, resultCleanup; + if (isSome) { + const enumResult = enumHelpers.AllTypesResult.lower(result); + resultCaseId = enumResult.caseId; + resultCleanup = enumResult.cleanup; + } + instance.exports.bjs_roundTripOptionalAllTypesResult(+isSome, isSome ? resultCaseId : 0); + const tag = i32Stack.pop(); + const isNull = (tag === -1); + let optResult; + if (isNull) { + optResult = null; + } else { + optResult = enumHelpers.AllTypesResult.lift(tag); + } + if (resultCleanup) { resultCleanup(); } + return optResult; + }, + roundTripOptionalPayloadResult: function bjs_roundTripOptionalPayloadResult(result) { + const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.OptionalAllTypesResult.lower(result); + instance.exports.bjs_roundTripOptionalPayloadResult(resultCaseId); + const ret = enumHelpers.OptionalAllTypesResult.lift(i32Stack.pop()); + if (resultCleanup) { resultCleanup(); } + return ret; + }, + roundTripOptionalPayloadResultOpt: function bjs_roundTripOptionalPayloadResultOpt(result) { + const isSome = result != null; + let resultCaseId, resultCleanup; + if (isSome) { + const enumResult = enumHelpers.OptionalAllTypesResult.lower(result); + resultCaseId = enumResult.caseId; + resultCleanup = enumResult.cleanup; + } + instance.exports.bjs_roundTripOptionalPayloadResultOpt(+isSome, isSome ? resultCaseId : 0); + const tag = i32Stack.pop(); + const isNull = (tag === -1); + let optResult; + if (isNull) { + optResult = null; + } else { + optResult = enumHelpers.OptionalAllTypesResult.lift(tag); + } + if (resultCleanup) { resultCleanup(); } + return optResult; + }, + APIResult: APIResultValues, + ComplexResult: ComplexResultValues, + APIOptionalResult: APIOptionalResultValues, + Precision: PrecisionValues, + CardinalDirection: CardinalDirectionValues, + TypedPayloadResult: TypedPayloadResultValues, + AllTypesResult: AllTypesResultValues, + OptionalAllTypesResult: OptionalAllTypesResultValues, + API: { + NetworkingResult: NetworkingResultValues, + }, + Utilities: { + Result: ResultValues, + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.d.ts new file mode 100644 index 000000000..5581df31e --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.d.ts @@ -0,0 +1,60 @@ +// 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 Loading: 0; + readonly Success: 1; + readonly Error: 2; +}; +export type StatusTag = typeof StatusValues[keyof typeof StatusValues]; + +export enum TSDirection { + North = 0, + South = 1, + East = 2, + West = 3, +} + +export const PublicStatusValues: { + readonly Success: 0; +}; +export type PublicStatusTag = typeof PublicStatusValues[keyof typeof PublicStatusValues]; + +export type DirectionObject = typeof DirectionValues; + +export type StatusObject = typeof StatusValues; + +export type PublicStatusObject = typeof PublicStatusValues; + +export type Exports = { + setDirection(direction: DirectionTag): void; + getDirection(): DirectionTag; + processDirection(input: DirectionTag): StatusTag; + roundTripOptionalDirection(input: DirectionTag | null): DirectionTag | null; + setTSDirection(direction: TSDirection): void; + getTSDirection(): TSDirection; + roundTripOptionalTSDirection(input: TSDirection | null): TSDirection | null; + Direction: DirectionObject + Status: StatusObject + PublicStatus: PublicStatusObject +} +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/EnumCase.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js new file mode 100644 index 000000000..72d78dbe0 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js @@ -0,0 +1,275 @@ +// 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 = { + Loading: 0, + Success: 1, + Error: 2, +}; + +export const TSDirection = { + North: 0, + South: 1, + East: 2, + West: 3, +}; + +export const PublicStatusValues = { + Success: 0, +}; + +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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + }, + 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 = { + setDirection: function bjs_setDirection(direction) { + instance.exports.bjs_setDirection(direction); + }, + getDirection: function bjs_getDirection() { + const ret = instance.exports.bjs_getDirection(); + return ret; + }, + processDirection: function bjs_processDirection(input) { + const ret = instance.exports.bjs_processDirection(input); + return ret; + }, + roundTripOptionalDirection: function bjs_roundTripOptionalDirection(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalDirection(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, + setTSDirection: function bjs_setTSDirection(direction) { + instance.exports.bjs_setTSDirection(direction); + }, + getTSDirection: function bjs_getTSDirection() { + const ret = instance.exports.bjs_getTSDirection(); + return ret; + }, + roundTripOptionalTSDirection: function bjs_roundTripOptionalTSDirection(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalTSDirection(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, + Direction: DirectionValues, + Status: StatusValues, + PublicStatus: PublicStatusValues, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.d.ts new file mode 100644 index 000000000..be77e759c --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.d.ts @@ -0,0 +1,138 @@ +// 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 type MethodObject = typeof Networking.API.MethodValues; + +export type LogLevelObject = typeof Configuration.LogLevelValues; + +export type PortObject = typeof Configuration.PortValues; + +export type SupportedMethodObject = typeof Networking.APIV2.Internal.SupportedMethodValues; + +export {}; + +declare global { + namespace Configuration { + const LogLevelValues: { + readonly Debug: "debug"; + readonly Info: "info"; + readonly Warning: "warning"; + readonly Error: "error"; + }; + type LogLevelTag = typeof LogLevelValues[keyof typeof LogLevelValues]; + const PortValues: { + readonly Http: 80; + readonly Https: 443; + readonly Development: 3000; + }; + type PortTag = typeof PortValues[keyof typeof PortValues]; + } + namespace Networking { + namespace API { + class HTTPServer { + constructor(); + call(method: Networking.API.MethodTag): void; + } + const MethodValues: { + readonly Get: 0; + readonly Post: 1; + readonly Put: 2; + readonly Delete: 3; + }; + type MethodTag = typeof MethodValues[keyof typeof MethodValues]; + } + namespace APIV2 { + namespace Internal { + class TestServer { + constructor(); + call(method: Networking.APIV2.Internal.SupportedMethodTag): void; + } + const SupportedMethodValues: { + readonly Get: 0; + readonly Post: 1; + }; + type SupportedMethodTag = typeof SupportedMethodValues[keyof typeof SupportedMethodValues]; + } + } + } + namespace Services { + namespace Graph { + namespace GraphOperations { + function createGraph(rootId: number): number; + function nodeCount(graphId: number): number; + function validate(graphId: number): boolean; + } + } + } + namespace Utils { + class Converter { + constructor(); + toString(value: number): string; + } + } +} + +/// 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 Converter extends SwiftHeapObject { + toString(value: number): string; +} +export interface HTTPServer extends SwiftHeapObject { + call(method: Networking.API.MethodTag): void; +} +export interface TestServer extends SwiftHeapObject { + call(method: Networking.APIV2.Internal.SupportedMethodTag): void; +} +export type Exports = { + Configuration: { + LogLevel: LogLevelObject + Port: PortObject + }, + Networking: { + API: { + HTTPServer: { + new(): HTTPServer; + } + Method: MethodObject + }, + APIV2: { + Internal: { + TestServer: { + new(): TestServer; + } + SupportedMethod: SupportedMethodObject + }, + }, + }, + Services: { + Graph: { + GraphOperations: { + createGraph(rootId: number): number; + nodeCount(graphId: number): number; + validate(graphId: number): boolean; + }, + }, + }, + Utils: { + Converter: { + new(): Converter; + } + }, +} +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/EnumNamespace.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js new file mode 100644 index 000000000..ee93a950a --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js @@ -0,0 +1,423 @@ +// 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 MethodValues = { + Get: 0, + Post: 1, + Put: 2, + Delete: 3, +}; + +export const LogLevelValues = { + Debug: "debug", + Info: "info", + Warning: "warning", + Error: "error", +}; + +export const PortValues = { + Http: 80, + Https: 443, + Development: 3000, +}; + +export const SupportedMethodValues = { + Get: 0, + Post: 1, +}; + +if (typeof globalThis.Configuration === 'undefined') { + globalThis.Configuration = {}; +} +if (typeof globalThis.Networking === 'undefined') { + globalThis.Networking = {}; +} +if (typeof globalThis.Networking.API === 'undefined') { + globalThis.Networking.API = {}; +} +if (typeof globalThis.Networking.APIV2 === 'undefined') { + globalThis.Networking.APIV2 = {}; +} +if (typeof globalThis.Networking.APIV2.Internal === 'undefined') { + globalThis.Networking.APIV2.Internal = {}; +} +globalThis.Networking.API.MethodValues = MethodValues; +globalThis.Configuration.LogLevelValues = LogLevelValues; +globalThis.Configuration.PortValues = PortValues; +globalThis.Networking.APIV2.Internal.SupportedMethodValues = SupportedMethodValues; +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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_Converter_wrap"] = function(pointer) { + const obj = _exports['Converter'].__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_HTTPServer_wrap"] = function(pointer) { + const obj = _exports['HTTPServer'].__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_TestServer_wrap"] = function(pointer) { + const obj = _exports['TestServer'].__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; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class Converter extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Converter_deinit, Converter.prototype); + } + + constructor() { + const ret = instance.exports.bjs_Converter_init(); + return Converter.__construct(ret); + } + toString(value) { + instance.exports.bjs_Converter_toString(this.pointer, value); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + } + class HTTPServer extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_HTTPServer_deinit, HTTPServer.prototype); + } + + constructor() { + const ret = instance.exports.bjs_HTTPServer_init(); + return HTTPServer.__construct(ret); + } + call(method) { + instance.exports.bjs_HTTPServer_call(this.pointer, method); + } + } + class TestServer extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_TestServer_deinit, TestServer.prototype); + } + + constructor() { + const ret = instance.exports.bjs_TestServer_init(); + return TestServer.__construct(ret); + } + call(method) { + instance.exports.bjs_TestServer_call(this.pointer, method); + } + } + if (typeof globalThis.Configuration === 'undefined') { + globalThis.Configuration = {}; + } + if (typeof globalThis.Networking === 'undefined') { + globalThis.Networking = {}; + } + if (typeof globalThis.Networking.API === 'undefined') { + globalThis.Networking.API = {}; + } + if (typeof globalThis.Networking.APIV2 === 'undefined') { + globalThis.Networking.APIV2 = {}; + } + if (typeof globalThis.Networking.APIV2.Internal === 'undefined') { + globalThis.Networking.APIV2.Internal = {}; + } + if (typeof globalThis.Services === 'undefined') { + globalThis.Services = {}; + } + if (typeof globalThis.Services.Graph === 'undefined') { + globalThis.Services.Graph = {}; + } + if (typeof globalThis.Services.Graph.GraphOperations === 'undefined') { + globalThis.Services.Graph.GraphOperations = {}; + } + if (typeof globalThis.Utils === 'undefined') { + globalThis.Utils = {}; + } + const exports = { + Configuration: { + LogLevel: LogLevelValues, + Port: PortValues, + }, + Networking: { + API: { + HTTPServer, + Method: MethodValues, + }, + APIV2: { + Internal: { + TestServer, + SupportedMethod: SupportedMethodValues, + }, + }, + }, + Services: { + Graph: { + GraphOperations: { + createGraph: function bjs_Services_Graph_GraphOperations_static_createGraph(rootId) { + const ret = instance.exports.bjs_Services_Graph_GraphOperations_static_createGraph(rootId); + return ret; + }, + nodeCount: function bjs_Services_Graph_GraphOperations_static_nodeCount(graphId) { + const ret = instance.exports.bjs_Services_Graph_GraphOperations_static_nodeCount(graphId); + return ret; + }, + validate: function bjs_Services_Graph_GraphOperations_static_validate(graphId) { + const ret = instance.exports.bjs_Services_Graph_GraphOperations_static_validate(graphId); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return ret !== 0; + }, + }, + }, + }, + Utils: { + Converter, + }, + }; + _exports = exports; + globalThis.Utils.Converter = exports.Utils.Converter; + globalThis.Networking.API.HTTPServer = exports.Networking.API.HTTPServer; + globalThis.Networking.APIV2.Internal.TestServer = exports.Networking.APIV2.Internal.TestServer; + globalThis.Services.Graph.GraphOperations.createGraph = exports.Services.Graph.GraphOperations.createGraph; + globalThis.Services.Graph.GraphOperations.nodeCount = exports.Services.Graph.GraphOperations.nodeCount; + globalThis.Services.Graph.GraphOperations.validate = exports.Services.Graph.GraphOperations.validate; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.d.ts new file mode 100644 index 000000000..a6934d6e7 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.d.ts @@ -0,0 +1,110 @@ +// 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 type MethodObject = typeof Networking.API.MethodValues; + +export type LogLevelObject = typeof Configuration.LogLevelValues; + +export type PortObject = typeof Configuration.PortValues; + +export type SupportedMethodObject = typeof Networking.APIV2.Internal.SupportedMethodValues; + +export namespace Configuration { + const LogLevelValues: { + readonly Debug: "debug"; + readonly Info: "info"; + readonly Warning: "warning"; + readonly Error: "error"; + }; + type LogLevelTag = typeof LogLevelValues[keyof typeof LogLevelValues]; + const PortValues: { + readonly Http: 80; + readonly Https: 443; + readonly Development: 3000; + }; + type PortTag = typeof PortValues[keyof typeof PortValues]; +} +export namespace Networking { + export namespace API { + const MethodValues: { + readonly Get: 0; + readonly Post: 1; + readonly Put: 2; + readonly Delete: 3; + }; + type MethodTag = typeof MethodValues[keyof typeof MethodValues]; + } + export namespace APIV2 { + export namespace Internal { + const SupportedMethodValues: { + readonly Get: 0; + readonly Post: 1; + }; + type SupportedMethodTag = typeof SupportedMethodValues[keyof typeof SupportedMethodValues]; + } + } +} +/// 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 Converter extends SwiftHeapObject { + toString(value: number): string; +} +export interface HTTPServer extends SwiftHeapObject { + call(method: Networking.API.MethodTag): void; +} +export interface TestServer extends SwiftHeapObject { + call(method: Networking.APIV2.Internal.SupportedMethodTag): void; +} +export type Exports = { + Configuration: { + LogLevel: LogLevelObject + Port: PortObject + }, + Networking: { + API: { + HTTPServer: { + new(): HTTPServer; + } + Method: MethodObject + }, + APIV2: { + Internal: { + TestServer: { + new(): TestServer; + } + SupportedMethod: SupportedMethodObject + }, + }, + }, + Services: { + Graph: { + GraphOperations: { + createGraph(rootId: number): number; + nodeCount(graphId: number): number; + validate(graphId: number): boolean; + }, + }, + }, + Utils: { + Converter: { + new(): Converter; + } + }, +} +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/EnumNamespace.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js new file mode 100644 index 000000000..099ef0576 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js @@ -0,0 +1,371 @@ +// 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 MethodValues = { + Get: 0, + Post: 1, + Put: 2, + Delete: 3, +}; + +export const LogLevelValues = { + Debug: "debug", + Info: "info", + Warning: "warning", + Error: "error", +}; + +export const PortValues = { + Http: 80, + Https: 443, + Development: 3000, +}; + +export const SupportedMethodValues = { + Get: 0, + Post: 1, +}; + +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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_Converter_wrap"] = function(pointer) { + const obj = _exports['Converter'].__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_HTTPServer_wrap"] = function(pointer) { + const obj = _exports['HTTPServer'].__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_TestServer_wrap"] = function(pointer) { + const obj = _exports['TestServer'].__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; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class Converter extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Converter_deinit, Converter.prototype); + } + + constructor() { + const ret = instance.exports.bjs_Converter_init(); + return Converter.__construct(ret); + } + toString(value) { + instance.exports.bjs_Converter_toString(this.pointer, value); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + } + class HTTPServer extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_HTTPServer_deinit, HTTPServer.prototype); + } + + constructor() { + const ret = instance.exports.bjs_HTTPServer_init(); + return HTTPServer.__construct(ret); + } + call(method) { + instance.exports.bjs_HTTPServer_call(this.pointer, method); + } + } + class TestServer extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_TestServer_deinit, TestServer.prototype); + } + + constructor() { + const ret = instance.exports.bjs_TestServer_init(); + return TestServer.__construct(ret); + } + call(method) { + instance.exports.bjs_TestServer_call(this.pointer, method); + } + } + const exports = { + Configuration: { + LogLevel: LogLevelValues, + Port: PortValues, + }, + Networking: { + API: { + HTTPServer, + Method: MethodValues, + }, + APIV2: { + Internal: { + TestServer, + SupportedMethod: SupportedMethodValues, + }, + }, + }, + Services: { + Graph: { + GraphOperations: { + createGraph: function bjs_Services_Graph_GraphOperations_static_createGraph(rootId) { + const ret = instance.exports.bjs_Services_Graph_GraphOperations_static_createGraph(rootId); + return ret; + }, + nodeCount: function bjs_Services_Graph_GraphOperations_static_nodeCount(graphId) { + const ret = instance.exports.bjs_Services_Graph_GraphOperations_static_nodeCount(graphId); + return ret; + }, + validate: function bjs_Services_Graph_GraphOperations_static_validate(graphId) { + const ret = instance.exports.bjs_Services_Graph_GraphOperations_static_validate(graphId); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return ret !== 0; + }, + }, + }, + }, + Utils: { + Converter, + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.d.ts new file mode 100644 index 000000000..50a45a58d --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.d.ts @@ -0,0 +1,173 @@ +// 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 ThemeValues: { + readonly Light: "light"; + readonly Dark: "dark"; + readonly Auto: "auto"; +}; +export type ThemeTag = typeof ThemeValues[keyof typeof ThemeValues]; + +export enum TSTheme { + Light = "light", + Dark = "dark", + Auto = "auto", +} + +export const FeatureFlagValues: { + readonly Enabled: true; + readonly Disabled: false; +}; +export type FeatureFlagTag = typeof FeatureFlagValues[keyof typeof FeatureFlagValues]; + +export const HttpStatusValues: { + readonly Ok: 200; + readonly NotFound: 404; + readonly ServerError: 500; +}; +export type HttpStatusTag = typeof HttpStatusValues[keyof typeof HttpStatusValues]; + +export enum TSHttpStatus { + Ok = 200, + NotFound = 404, + ServerError = 500, +} + +export const PriorityValues: { + readonly Lowest: -1; + readonly Low: 2; + readonly Medium: 3; + readonly High: 4; + readonly Highest: 5; +}; +export type PriorityTag = typeof PriorityValues[keyof typeof PriorityValues]; + +export const FileSizeValues: { + readonly Tiny: 1024; + readonly Small: 10240; + readonly Medium: 102400; + readonly Large: 1048576; +}; +export type FileSizeTag = typeof FileSizeValues[keyof typeof FileSizeValues]; + +export const UserIdValues: { + readonly Guest: 0; + readonly User: 1000; + readonly Admin: 9999; +}; +export type UserIdTag = typeof UserIdValues[keyof typeof UserIdValues]; + +export const TokenIdValues: { + readonly Invalid: 0; + readonly Session: 12345; + readonly Refresh: 67890; +}; +export type TokenIdTag = typeof TokenIdValues[keyof typeof TokenIdValues]; + +export const SessionIdValues: { + readonly None: 0; + readonly Active: 9876543210; + readonly Expired: 1234567890; +}; +export type SessionIdTag = typeof SessionIdValues[keyof typeof SessionIdValues]; + +export const PrecisionValues: { + readonly Rough: 0.1; + readonly Normal: 0.01; + readonly Fine: 0.001; +}; +export type PrecisionTag = typeof PrecisionValues[keyof typeof PrecisionValues]; + +export const RatioValues: { + readonly Quarter: 0.25; + readonly Half: 0.5; + readonly Golden: 1.618; + readonly Pi: 3.14159; +}; +export type RatioTag = typeof RatioValues[keyof typeof RatioValues]; + +export type ThemeObject = typeof ThemeValues; + +export type FeatureFlagObject = typeof FeatureFlagValues; + +export type HttpStatusObject = typeof HttpStatusValues; + +export type PriorityObject = typeof PriorityValues; + +export type FileSizeObject = typeof FileSizeValues; + +export type UserIdObject = typeof UserIdValues; + +export type TokenIdObject = typeof TokenIdValues; + +export type SessionIdObject = typeof SessionIdValues; + +export type PrecisionObject = typeof PrecisionValues; + +export type RatioObject = typeof RatioValues; + +export type Exports = { + setTheme(theme: ThemeTag): void; + getTheme(): ThemeTag; + roundTripOptionalTheme(input: ThemeTag | null): ThemeTag | null; + setTSTheme(theme: TSTheme): void; + getTSTheme(): TSTheme; + roundTripOptionalTSTheme(input: TSTheme | null): TSTheme | null; + setFeatureFlag(flag: FeatureFlagTag): void; + getFeatureFlag(): FeatureFlagTag; + roundTripOptionalFeatureFlag(input: FeatureFlagTag | null): FeatureFlagTag | null; + setHttpStatus(status: HttpStatusTag): void; + getHttpStatus(): HttpStatusTag; + roundTripOptionalHttpStatus(input: HttpStatusTag | null): HttpStatusTag | null; + setTSHttpStatus(status: TSHttpStatus): void; + getTSHttpStatus(): TSHttpStatus; + roundTripOptionalHttpStatus(input: TSHttpStatus | null): TSHttpStatus | null; + setPriority(priority: PriorityTag): void; + getPriority(): PriorityTag; + roundTripOptionalPriority(input: PriorityTag | null): PriorityTag | null; + setFileSize(size: FileSizeTag): void; + getFileSize(): FileSizeTag; + roundTripOptionalFileSize(input: FileSizeTag | null): FileSizeTag | null; + setUserId(id: UserIdTag): void; + getUserId(): UserIdTag; + roundTripOptionalUserId(input: UserIdTag | null): UserIdTag | null; + setTokenId(token: TokenIdTag): void; + getTokenId(): TokenIdTag; + roundTripOptionalTokenId(input: TokenIdTag | null): TokenIdTag | null; + setSessionId(session: SessionIdTag): void; + getSessionId(): SessionIdTag; + roundTripOptionalSessionId(input: SessionIdTag | null): SessionIdTag | null; + setPrecision(precision: PrecisionTag): void; + getPrecision(): PrecisionTag; + roundTripOptionalPrecision(input: PrecisionTag | null): PrecisionTag | null; + setRatio(ratio: RatioTag): void; + getRatio(): RatioTag; + roundTripOptionalRatio(input: RatioTag | null): RatioTag | null; + processTheme(theme: ThemeTag): HttpStatusTag; + convertPriority(status: HttpStatusTag): PriorityTag; + validateSession(session: SessionIdTag): ThemeTag; + Theme: ThemeObject + FeatureFlag: FeatureFlagObject + HttpStatus: HttpStatusObject + Priority: PriorityObject + FileSize: FileSizeObject + UserId: UserIdObject + TokenId: TokenIdObject + SessionId: SessionIdObject + Precision: PrecisionObject + Ratio: RatioObject +} +export type Imports = { + takesFeatureFlag(flag: FeatureFlagTag): void; + returnsFeatureFlag(): FeatureFlagTag; +} +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/EnumRawType.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js new file mode 100644 index 000000000..b1ee0538f --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js @@ -0,0 +1,532 @@ +// 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 ThemeValues = { + Light: "light", + Dark: "dark", + Auto: "auto", +}; + +export const TSTheme = { + Light: "light", + Dark: "dark", + Auto: "auto", +}; + +export const FeatureFlagValues = { + Enabled: true, + Disabled: false, +}; + +export const HttpStatusValues = { + Ok: 200, + NotFound: 404, + ServerError: 500, +}; + +export const TSHttpStatus = { + Ok: 200, + NotFound: 404, + ServerError: 500, +}; + +export const PriorityValues = { + Lowest: -1, + Low: 2, + Medium: 3, + High: 4, + Highest: 5, +}; + +export const FileSizeValues = { + Tiny: 1024, + Small: 10240, + Medium: 102400, + Large: 1048576, +}; + +export const UserIdValues = { + Guest: 0, + User: 1000, + Admin: 9999, +}; + +export const TokenIdValues = { + Invalid: 0, + Session: 12345, + Refresh: 67890, +}; + +export const SessionIdValues = { + None: 0, + Active: 9876543210, + Expired: 1234567890, +}; + +export const PrecisionValues = { + Rough: 0.1, + Normal: 0.01, + Fine: 0.001, +}; + +export const RatioValues = { + Quarter: 0.25, + Half: 0.5, + Golden: 1.618, + Pi: 3.14159, +}; + +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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_takesFeatureFlag"] = function bjs_takesFeatureFlag(flag) { + try { + const flagObject = swift.memory.getObject(flag); + swift.memory.release(flag); + imports.takesFeatureFlag(flagObject); + } catch (error) { + setException(error); + } + } + TestModule["bjs_returnsFeatureFlag"] = function bjs_returnsFeatureFlag() { + try { + let ret = imports.returnsFeatureFlag(); + tmpRetBytes = textEncoder.encode(ret); + return tmpRetBytes.length; + } 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 = { + setTheme: function bjs_setTheme(theme) { + const themeBytes = textEncoder.encode(theme); + const themeId = swift.memory.retain(themeBytes); + instance.exports.bjs_setTheme(themeId, themeBytes.length); + }, + getTheme: function bjs_getTheme() { + instance.exports.bjs_getTheme(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + roundTripOptionalTheme: function bjs_roundTripOptionalTheme(input) { + const isSome = input != null; + let inputId, inputBytes; + if (isSome) { + inputBytes = textEncoder.encode(input); + inputId = swift.memory.retain(inputBytes); + } + instance.exports.bjs_roundTripOptionalTheme(+isSome, isSome ? inputId : 0, isSome ? inputBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + }, + setTSTheme: function bjs_setTSTheme(theme) { + const themeBytes = textEncoder.encode(theme); + const themeId = swift.memory.retain(themeBytes); + instance.exports.bjs_setTSTheme(themeId, themeBytes.length); + }, + getTSTheme: function bjs_getTSTheme() { + instance.exports.bjs_getTSTheme(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + roundTripOptionalTSTheme: function bjs_roundTripOptionalTSTheme(input) { + const isSome = input != null; + let inputId, inputBytes; + if (isSome) { + inputBytes = textEncoder.encode(input); + inputId = swift.memory.retain(inputBytes); + } + instance.exports.bjs_roundTripOptionalTSTheme(+isSome, isSome ? inputId : 0, isSome ? inputBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + }, + setFeatureFlag: function bjs_setFeatureFlag(flag) { + const flagBytes = textEncoder.encode(flag); + const flagId = swift.memory.retain(flagBytes); + instance.exports.bjs_setFeatureFlag(flagId, flagBytes.length); + }, + getFeatureFlag: function bjs_getFeatureFlag() { + instance.exports.bjs_getFeatureFlag(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + roundTripOptionalFeatureFlag: function bjs_roundTripOptionalFeatureFlag(input) { + const isSome = input != null; + let inputId, inputBytes; + if (isSome) { + inputBytes = textEncoder.encode(input); + inputId = swift.memory.retain(inputBytes); + } + instance.exports.bjs_roundTripOptionalFeatureFlag(+isSome, isSome ? inputId : 0, isSome ? inputBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + }, + setHttpStatus: function bjs_setHttpStatus(status) { + instance.exports.bjs_setHttpStatus(status); + }, + getHttpStatus: function bjs_getHttpStatus() { + const ret = instance.exports.bjs_getHttpStatus(); + return ret; + }, + roundTripOptionalHttpStatus: function bjs_roundTripOptionalHttpStatus(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalHttpStatus(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, + setTSHttpStatus: function bjs_setTSHttpStatus(status) { + instance.exports.bjs_setTSHttpStatus(status); + }, + getTSHttpStatus: function bjs_getTSHttpStatus() { + const ret = instance.exports.bjs_getTSHttpStatus(); + return ret; + }, + roundTripOptionalHttpStatus: function bjs_roundTripOptionalHttpStatus(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalHttpStatus(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, + setPriority: function bjs_setPriority(priority) { + instance.exports.bjs_setPriority(priority); + }, + getPriority: function bjs_getPriority() { + const ret = instance.exports.bjs_getPriority(); + return ret; + }, + roundTripOptionalPriority: function bjs_roundTripOptionalPriority(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalPriority(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, + setFileSize: function bjs_setFileSize(size) { + instance.exports.bjs_setFileSize(size); + }, + getFileSize: function bjs_getFileSize() { + const ret = instance.exports.bjs_getFileSize(); + return ret; + }, + roundTripOptionalFileSize: function bjs_roundTripOptionalFileSize(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalFileSize(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, + setUserId: function bjs_setUserId(id) { + instance.exports.bjs_setUserId(id); + }, + getUserId: function bjs_getUserId() { + const ret = instance.exports.bjs_getUserId(); + return ret; + }, + roundTripOptionalUserId: function bjs_roundTripOptionalUserId(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalUserId(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, + setTokenId: function bjs_setTokenId(token) { + instance.exports.bjs_setTokenId(token); + }, + getTokenId: function bjs_getTokenId() { + const ret = instance.exports.bjs_getTokenId(); + return ret; + }, + roundTripOptionalTokenId: function bjs_roundTripOptionalTokenId(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalTokenId(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, + setSessionId: function bjs_setSessionId(session) { + instance.exports.bjs_setSessionId(session); + }, + getSessionId: function bjs_getSessionId() { + const ret = instance.exports.bjs_getSessionId(); + return ret; + }, + roundTripOptionalSessionId: function bjs_roundTripOptionalSessionId(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalSessionId(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, + setPrecision: function bjs_setPrecision(precision) { + instance.exports.bjs_setPrecision(precision); + }, + getPrecision: function bjs_getPrecision() { + const ret = instance.exports.bjs_getPrecision(); + return ret; + }, + roundTripOptionalPrecision: function bjs_roundTripOptionalPrecision(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalPrecision(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; + return optResult; + }, + setRatio: function bjs_setRatio(ratio) { + instance.exports.bjs_setRatio(ratio); + }, + getRatio: function bjs_getRatio() { + const ret = instance.exports.bjs_getRatio(); + return ret; + }, + roundTripOptionalRatio: function bjs_roundTripOptionalRatio(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalRatio(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + return optResult; + }, + processTheme: function bjs_processTheme(theme) { + const themeBytes = textEncoder.encode(theme); + const themeId = swift.memory.retain(themeBytes); + const ret = instance.exports.bjs_processTheme(themeId, themeBytes.length); + return ret; + }, + convertPriority: function bjs_convertPriority(status) { + const ret = instance.exports.bjs_convertPriority(status); + return ret; + }, + validateSession: function bjs_validateSession(session) { + instance.exports.bjs_validateSession(session); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + Theme: ThemeValues, + FeatureFlag: FeatureFlagValues, + HttpStatus: HttpStatusValues, + Priority: PriorityValues, + FileSize: FileSizeValues, + UserId: UserIdValues, + TokenId: TokenIdValues, + SessionId: SessionIdValues, + Precision: PrecisionValues, + Ratio: RatioValues, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.d.ts similarity index 84% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.d.ts rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.d.ts index a83fca6f5..312f56786 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.d.ts @@ -4,10 +4,13 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. +export interface JSConsole { + log(message: string): void; +} export type Exports = { - checkString(a: string): void; } export type Imports = { + readonly console: JSConsole; } export function createInstantiator(options: { imports: Imports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js new file mode 100644 index 000000000..6f6bf9531 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js @@ -0,0 +1,236 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_console_get"] = function bjs_console_get() { + try { + let ret = imports.console; + return swift.memory.retain(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); + } + } + }, + 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/ArrayParameter.Import.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.d.ts similarity index 81% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.d.ts rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.d.ts index 2a6771ca7..ae1152016 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.d.ts @@ -4,12 +4,15 @@ // 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 = { - checkArray(a: any): void; - checkArrayWithLength(a: any, b: number): void; - checkArray(a: any): void; } export function createInstantiator(options: { imports: Imports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js new file mode 100644 index 000000000..9d57a04d3 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js @@ -0,0 +1,263 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + 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/PrimitiveParameters.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.d.ts similarity index 86% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.d.ts rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.d.ts index a9c37f378..5d1e2c4dc 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.d.ts @@ -5,9 +5,10 @@ // `swift package bridge-js`. export type Exports = { - check(a: number, b: number, c: number, d: boolean): void; } export type Imports = { + roundtrip(items: number[]): number[]; + logStrings(items: string[]): void; } export function createInstantiator(options: { imports: Imports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js new file mode 100644 index 000000000..7c946a716 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js @@ -0,0 +1,251 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_roundtrip"] = function bjs_roundtrip() { + try { + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); + let ret = imports.roundtrip(arrayResult); + const arrayCleanups = []; + for (const elem of ret) { + i32Stack.push((elem | 0)); + } + i32Stack.push(ret.length); + } catch (error) { + setException(error); + } + } + TestModule["bjs_logStrings"] = function bjs_logStrings() { + try { + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const string = strStack.pop(); + arrayResult.push(string); + } + arrayResult.reverse(); + imports.logStrings(arrayResult); + } 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/Interface.Import.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.d.ts similarity index 60% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.d.ts rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.d.ts index ccd371b71..22b4e6a1c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.d.ts @@ -4,14 +4,22 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. -export interface Animatable { - animate(keyframes: any, options: any): any; - getAnimations(options: any): any; +export interface FooContainer { + foo: Foo; + optionalFoo: Foo | null; +} +export interface Foo { } export type Exports = { + makeFoo(): Foo; + processFooArray(foos: Foo[]): Foo[]; + processOptionalFooArray(foos: (Foo | null)[]): (Foo | null)[]; + roundtripFooContainer(container: FooContainer): FooContainer; } export type Imports = { - returnAnimatable(): Animatable; + Foo: { + new(): Foo; + } } export function createInstantiator(options: { imports: Imports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js new file mode 100644 index 000000000..5d724202b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js @@ -0,0 +1,362 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createFooContainerHelpers = () => { + return () => ({ + lower: (value) => { + let id; + if (value.foo != null) { + id = swift.memory.retain(value.foo); + } else { + id = undefined; + } + i32Stack.push(id !== undefined ? id : 0); + const isSome = value.optionalFoo != null; + let id1; + if (isSome) { + id1 = swift.memory.retain(value.optionalFoo); + i32Stack.push(id1); + } else { + id1 = undefined; + i32Stack.push(0); + } + i32Stack.push(isSome ? 1 : 0); + return { cleanup: undefined }; + }, + lift: () => { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const objectId = i32Stack.pop(); + let value; + if (objectId !== 0) { + value = swift.memory.getObject(objectId); + swift.memory.release(objectId); + } else { + value = null; + } + optional = value; + } else { + optional = null; + } + const objectId1 = i32Stack.pop(); + let value1; + if (objectId1 !== 0) { + value1 = swift.memory.getObject(objectId1); + swift.memory.release(objectId1); + } else { + value1 = null; + } + return { foo: value1, optionalFoo: optional }; + } + }); + }; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_struct_lower_FooContainer"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.FooContainer.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_FooContainer"] = function() { + const value = structHelpers.FooContainer.lift(); + 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_Foo_init"] = function bjs_Foo_init() { + try { + return swift.memory.retain(new imports.Foo()); + } catch (error) { + setException(error); + return 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 FooContainerHelpers = __bjs_createFooContainerHelpers()(); + structHelpers.FooContainer = FooContainerHelpers; + + const exports = { + makeFoo: function bjs_makeFoo() { + const ret = instance.exports.bjs_makeFoo(); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return ret1; + }, + processFooArray: function bjs_processFooArray(foos) { + const arrayCleanups = []; + for (const elem of foos) { + const objId = swift.memory.retain(elem); + i32Stack.push(objId); + } + i32Stack.push(foos.length); + instance.exports.bjs_processFooArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const objId1 = i32Stack.pop(); + const obj = swift.memory.getObject(objId1); + swift.memory.release(objId1); + arrayResult.push(obj); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + processOptionalFooArray: function bjs_processOptionalFooArray(foos) { + const arrayCleanups = []; + for (const elem of foos) { + const isSome = elem != null ? 1 : 0; + if (isSome) { + const objId = swift.memory.retain(elem); + i32Stack.push(objId); + } else { + i32Stack.push(0); + } + i32Stack.push(isSome); + } + i32Stack.push(foos.length); + instance.exports.bjs_processOptionalFooArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const isSome1 = i32Stack.pop(); + let optValue; + if (isSome1 === 0) { + optValue = null; + } else { + const objId1 = i32Stack.pop(); + const obj = swift.memory.getObject(objId1); + swift.memory.release(objId1); + optValue = obj; + } + arrayResult.push(optValue); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + roundtripFooContainer: function bjs_roundtripFooContainer(container) { + const { cleanup: cleanup } = structHelpers.FooContainer.lower(container); + instance.exports.bjs_roundtripFooContainer(); + const structValue = structHelpers.FooContainer.lift(); + if (cleanup) { cleanup(); } + return structValue; + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.js deleted file mode 100644 index f81c7e475..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.js +++ /dev/null @@ -1,98 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_returnAnimatable"] = function bjs_returnAnimatable() { - try { - let ret = imports.returnAnimatable(); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_Animatable_animate"] = function bjs_Animatable_animate(self, keyframes, options) { - try { - let ret = swift.memory.getObject(self).animate(swift.memory.getObject(keyframes), swift.memory.getObject(options)); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_Animatable_getAnimations"] = function bjs_Animatable_getAnimations(self, options) { - try { - let ret = swift.memory.getObject(self).getAnimations(swift.memory.getObject(options)); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 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; - - return { - - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.d.ts new file mode 100644 index 000000000..ac0e05a91 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.d.ts @@ -0,0 +1,37 @@ +// 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 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 = { + createWeirdObject(): WeirdNaming; + createWeirdClass(): _Weird; + _Weird: { + new(): _Weird; + } +} +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/InvalidPropertyNames.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js new file mode 100644 index 000000000..54a0f2018 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js @@ -0,0 +1,403 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_createWeirdObject"] = function bjs_createWeirdObject() { + try { + let ret = imports.createWeirdObject(); + return swift.memory.retain(ret); + } catch (error) { + setException(error); + 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_WeirdNaming_normalProperty_get"] = function bjs_WeirdNaming_normalProperty_get(self) { + try { + let ret = swift.memory.getObject(self).normalProperty; + tmpRetBytes = textEncoder.encode(ret); + return tmpRetBytes.length; + } catch (error) { + 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; + tmpRetBytes = textEncoder.encode(ret); + return tmpRetBytes.length; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WeirdNaming_Any_get"] = function bjs_WeirdNaming_Any_get(self) { + try { + let ret = swift.memory.getObject(self).Any; + tmpRetBytes = textEncoder.encode(ret); + return tmpRetBytes.length; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WeirdNaming_normalProperty_set"] = function bjs_WeirdNaming_normalProperty_set(self, newValue) { + try { + const newValueObject = swift.memory.getObject(newValue); + swift.memory.release(newValue); + swift.memory.getObject(self).normalProperty = newValueObject; + } catch (error) { + 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); + swift.memory.release(newValue); + swift.memory.getObject(self).for = newValueObject; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WeirdNaming_any_set"] = function bjs_WeirdNaming_any_set(self, newValue) { + try { + const newValueObject = swift.memory.getObject(newValue); + swift.memory.release(newValue); + swift.memory.getObject(self).Any = newValueObject; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WeirdNaming_as"] = function bjs_WeirdNaming_as(self) { + try { + swift.memory.getObject(self).as(); + } catch (error) { + 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; + 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/TypeScriptClass.Import.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.d.ts similarity index 81% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.d.ts rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.d.ts index 24d3d8fac..aaf227cf7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.d.ts @@ -10,9 +10,14 @@ export interface Greeter { name: string; readonly age: number; } +export interface Animatable { + animate(keyframes: any, options: any): any; + getAnimations(options: any): any; +} export type Exports = { } export type Imports = { + returnAnimatable(): Animatable; Greeter: { new(name: string): Greeter; } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js new file mode 100644 index 000000000..a192a1a8b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js @@ -0,0 +1,300 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_returnAnimatable"] = function bjs_returnAnimatable() { + try { + let ret = imports.returnAnimatable(); + return swift.memory.retain(ret); + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_Greeter_init"] = function bjs_Greeter_init(name) { + try { + const nameObject = swift.memory.getObject(name); + swift.memory.release(name); + return swift.memory.retain(new imports.Greeter(nameObject)); + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_Greeter_name_get"] = function bjs_Greeter_name_get(self) { + try { + let ret = swift.memory.getObject(self).name; + tmpRetBytes = textEncoder.encode(ret); + return tmpRetBytes.length; + } catch (error) { + setException(error); + } + } + TestModule["bjs_Greeter_age_get"] = function bjs_Greeter_age_get(self) { + try { + let ret = swift.memory.getObject(self).age; + return ret; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_Greeter_name_set"] = function bjs_Greeter_name_set(self, newValue) { + try { + const newValueObject = swift.memory.getObject(newValue); + swift.memory.release(newValue); + swift.memory.getObject(self).name = newValueObject; + } catch (error) { + setException(error); + } + } + TestModule["bjs_Greeter_greet"] = function bjs_Greeter_greet(self) { + try { + let ret = swift.memory.getObject(self).greet(); + tmpRetBytes = textEncoder.encode(ret); + return tmpRetBytes.length; + } catch (error) { + setException(error); + } + } + TestModule["bjs_Greeter_changeName"] = function bjs_Greeter_changeName(self, name) { + try { + const nameObject = swift.memory.getObject(name); + swift.memory.release(name); + swift.memory.getObject(self).changeName(nameObject); + } catch (error) { + setException(error); + } + } + TestModule["bjs_Animatable_animate"] = function bjs_Animatable_animate(self, keyframes, options) { + try { + let ret = swift.memory.getObject(self).animate(swift.memory.getObject(keyframes), swift.memory.getObject(options)); + return swift.memory.retain(ret); + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_Animatable_getAnimations"] = function bjs_Animatable_getAnimations(self, options) { + try { + let ret = swift.memory.getObject(self).getAnimations(swift.memory.getObject(options)); + return swift.memory.retain(ret); + } catch (error) { + setException(error); + return 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 exports = { + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.d.ts similarity index 60% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.d.ts rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.d.ts index 26d56fb6c..3b2b5de99 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.d.ts @@ -4,20 +4,24 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. -export interface TypeScriptProcessor { - convert(ts: string): string; - validate(ts: string): boolean; - readonly version: string; +export interface StaticBox { + value(): number; } -export interface CodeGenerator { - generate(input: any): string; - readonly outputFormat: string; +export interface WithCtor { } export type Exports = { } export type Imports = { - createTS2Skeleton(): TypeScriptProcessor; - createCodeGenerator(format: string): CodeGenerator; + StaticBox: { + create(value: number): StaticBox; + value(): number; + makeDefault(): StaticBox; + "with-dashes"(): StaticBox; + } + WithCtor: { + new(value: number): WithCtor; + create(value: number): WithCtor; + } } export function createInstantiator(options: { imports: Imports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js new file mode 100644 index 000000000..1166d1f62 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js @@ -0,0 +1,280 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_StaticBox_create_static"] = function bjs_StaticBox_create_static(value) { + try { + let ret = imports.StaticBox.create(value); + return swift.memory.retain(ret); + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_StaticBox_value_static"] = function bjs_StaticBox_value_static() { + try { + let ret = imports.StaticBox.value(); + return ret; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_StaticBox_makeDefault_static"] = function bjs_StaticBox_makeDefault_static() { + try { + let ret = imports.StaticBox.makeDefault(); + return swift.memory.retain(ret); + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_StaticBox_dashed_static"] = function bjs_StaticBox_dashed_static() { + try { + let ret = imports.StaticBox["with-dashes"](); + return swift.memory.retain(ret); + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_StaticBox_value"] = function bjs_StaticBox_value(self) { + try { + let ret = swift.memory.getObject(self).value(); + return ret; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_WithCtor_init"] = function bjs_WithCtor_init(value) { + try { + return swift.memory.retain(new imports.WithCtor(value)); + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_WithCtor_create_static"] = function bjs_WithCtor_create_static(value) { + try { + let ret = imports.WithCtor.create(value); + return swift.memory.retain(ret); + } catch (error) { + setException(error); + return 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 exports = { + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.d.ts new file mode 100644 index 000000000..f4c13c610 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.d.ts @@ -0,0 +1,40 @@ +// 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`. + +/// 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 JSValueHolder extends SwiftHeapObject { + update(value: any, optionalValue: any | null): void; + echo(value: any): any; + echoOptional(value: any | null): any | null; + value: any; + optionalValue: any | null; +} +export type Exports = { + JSValueHolder: { + new(value: any, optionalValue: any | null): JSValueHolder; + } + roundTripJSValue(value: any): any; + roundTripOptionalJSValue(value: any | null): any | null; + roundTripJSValueArray(values: any[]): any[]; + roundTripOptionalJSValueArray(values: any[] | null): any[] | null; +} +export type Imports = { + jsEchoJSValue(value: any): any; + jsEchoJSValueArray(values: any[]): any[]; +} +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/JSValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js new file mode 100644 index 000000000..8151ea913 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js @@ -0,0 +1,544 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + function __bjs_jsValueLower(value) { + let kind; + let payload1; + let payload2; + if (value === null) { + kind = 4; + payload1 = 0; + payload2 = 0; + } else { + switch (typeof value) { + case "boolean": + kind = 0; + payload1 = value ? 1 : 0; + payload2 = 0; + break; + case "number": + kind = 2; + payload1 = 0; + payload2 = value; + break; + case "string": + kind = 1; + payload1 = swift.memory.retain(value); + payload2 = 0; + break; + case "undefined": + kind = 5; + payload1 = 0; + payload2 = 0; + break; + case "object": + kind = 3; + payload1 = swift.memory.retain(value); + payload2 = 0; + break; + case "function": + kind = 3; + payload1 = swift.memory.retain(value); + payload2 = 0; + break; + case "symbol": + kind = 7; + payload1 = swift.memory.retain(value); + payload2 = 0; + break; + case "bigint": + kind = 8; + payload1 = swift.memory.retain(value); + payload2 = 0; + break; + default: + throw new TypeError("Unsupported JSValue type"); + } + } + return [kind, payload1, payload2]; + } + function __bjs_jsValueLift(kind, payload1, payload2) { + let jsValue; + switch (kind) { + case 0: + jsValue = payload1 !== 0; + break; + case 1: + jsValue = swift.memory.getObject(payload1); + break; + case 2: + jsValue = payload2; + break; + case 3: + jsValue = swift.memory.getObject(payload1); + break; + case 4: + jsValue = null; + break; + case 5: + jsValue = undefined; + break; + case 7: + jsValue = swift.memory.getObject(payload1); + break; + case 8: + jsValue = swift.memory.getObject(payload1); + break; + default: + throw new TypeError("Unsupported JSValue kind " + kind); + } + return jsValue; + } + + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_JSValueHolder_wrap"] = function(pointer) { + const obj = _exports['JSValueHolder'].__construct(pointer); + return swift.memory.retain(obj); + }; + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_jsEchoJSValue"] = function bjs_jsEchoJSValue(valueKind, valuePayload1, valuePayload2) { + try { + const jsValue = __bjs_jsValueLift(valueKind, valuePayload1, valuePayload2); + let ret = imports.jsEchoJSValue(jsValue); + const [retKind, retPayload1, retPayload2] = __bjs_jsValueLower(ret); + i32Stack.push(retKind); + i32Stack.push(retPayload1); + f64Stack.push(retPayload2); + } catch (error) { + setException(error); + } + } + TestModule["bjs_jsEchoJSValueArray"] = function bjs_jsEchoJSValueArray() { + try { + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const jsValuePayload2 = f64Stack.pop(); + const jsValuePayload1 = i32Stack.pop(); + const jsValueKind = i32Stack.pop(); + const jsValue = __bjs_jsValueLift(jsValueKind, jsValuePayload1, jsValuePayload2); + arrayResult.push(jsValue); + } + arrayResult.reverse(); + let ret = imports.jsEchoJSValueArray(arrayResult); + const arrayCleanups = []; + for (const elem of ret) { + const [elemKind, elemPayload1, elemPayload2] = __bjs_jsValueLower(elem); + i32Stack.push(elemKind); + i32Stack.push(elemPayload1); + f64Stack.push(elemPayload2); + } + i32Stack.push(ret.length); + } 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 swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class JSValueHolder extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_JSValueHolder_deinit, JSValueHolder.prototype); + } + + constructor(value, optionalValue) { + const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); + const isSome = optionalValue != null; + const [optionalValueKind, optionalValuePayload1, optionalValuePayload2] = __bjs_jsValueLower(optionalValue); + const ret = instance.exports.bjs_JSValueHolder_init(valueKind, valuePayload1, valuePayload2, +isSome, optionalValueKind, optionalValuePayload1, optionalValuePayload2); + return JSValueHolder.__construct(ret); + } + update(value, optionalValue) { + const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); + const isSome = optionalValue != null; + const [optionalValueKind, optionalValuePayload1, optionalValuePayload2] = __bjs_jsValueLower(optionalValue); + instance.exports.bjs_JSValueHolder_update(this.pointer, valueKind, valuePayload1, valuePayload2, +isSome, optionalValueKind, optionalValuePayload1, optionalValuePayload2); + } + echo(value) { + const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); + instance.exports.bjs_JSValueHolder_echo(this.pointer, valueKind, valuePayload1, valuePayload2); + const jsValuePayload2 = f64Stack.pop(); + const jsValuePayload1 = i32Stack.pop(); + const jsValueKind = i32Stack.pop(); + const jsValue = __bjs_jsValueLift(jsValueKind, jsValuePayload1, jsValuePayload2); + return jsValue; + } + echoOptional(value) { + const isSome = value != null; + const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); + instance.exports.bjs_JSValueHolder_echoOptional(this.pointer, +isSome, valueKind, valuePayload1, valuePayload2); + const isSome1 = i32Stack.pop(); + let optResult; + if (isSome1) { + const jsValuePayload2 = f64Stack.pop(); + const jsValuePayload1 = i32Stack.pop(); + const jsValueKind = i32Stack.pop(); + const jsValue = __bjs_jsValueLift(jsValueKind, jsValuePayload1, jsValuePayload2); + optResult = jsValue; + } else { + optResult = null; + } + return optResult; + } + get value() { + instance.exports.bjs_JSValueHolder_value_get(this.pointer); + const jsValuePayload2 = f64Stack.pop(); + const jsValuePayload1 = i32Stack.pop(); + const jsValueKind = i32Stack.pop(); + const jsValue = __bjs_jsValueLift(jsValueKind, jsValuePayload1, jsValuePayload2); + return jsValue; + } + set value(value) { + const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); + instance.exports.bjs_JSValueHolder_value_set(this.pointer, valueKind, valuePayload1, valuePayload2); + } + get optionalValue() { + instance.exports.bjs_JSValueHolder_optionalValue_get(this.pointer); + const isSome = i32Stack.pop(); + let optResult; + if (isSome) { + const jsValuePayload2 = f64Stack.pop(); + const jsValuePayload1 = i32Stack.pop(); + const jsValueKind = i32Stack.pop(); + const jsValue = __bjs_jsValueLift(jsValueKind, jsValuePayload1, jsValuePayload2); + optResult = jsValue; + } else { + optResult = null; + } + return optResult; + } + set optionalValue(value) { + const isSome = value != null; + const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); + instance.exports.bjs_JSValueHolder_optionalValue_set(this.pointer, +isSome, valueKind, valuePayload1, valuePayload2); + } + } + const exports = { + JSValueHolder, + roundTripJSValue: function bjs_roundTripJSValue(value) { + const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); + instance.exports.bjs_roundTripJSValue(valueKind, valuePayload1, valuePayload2); + const jsValuePayload2 = f64Stack.pop(); + const jsValuePayload1 = i32Stack.pop(); + const jsValueKind = i32Stack.pop(); + const jsValue = __bjs_jsValueLift(jsValueKind, jsValuePayload1, jsValuePayload2); + return jsValue; + }, + roundTripOptionalJSValue: function bjs_roundTripOptionalJSValue(value) { + const isSome = value != null; + const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); + instance.exports.bjs_roundTripOptionalJSValue(+isSome, valueKind, valuePayload1, valuePayload2); + const isSome1 = i32Stack.pop(); + let optResult; + if (isSome1) { + const jsValuePayload2 = f64Stack.pop(); + const jsValuePayload1 = i32Stack.pop(); + const jsValueKind = i32Stack.pop(); + const jsValue = __bjs_jsValueLift(jsValueKind, jsValuePayload1, jsValuePayload2); + optResult = jsValue; + } else { + optResult = null; + } + return optResult; + }, + roundTripJSValueArray: function bjs_roundTripJSValueArray(values) { + const arrayCleanups = []; + for (const elem of values) { + const [elemKind, elemPayload1, elemPayload2] = __bjs_jsValueLower(elem); + i32Stack.push(elemKind); + i32Stack.push(elemPayload1); + f64Stack.push(elemPayload2); + } + i32Stack.push(values.length); + instance.exports.bjs_roundTripJSValueArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const jsValuePayload2 = f64Stack.pop(); + const jsValuePayload1 = i32Stack.pop(); + const jsValueKind = i32Stack.pop(); + const jsValue = __bjs_jsValueLift(jsValueKind, jsValuePayload1, jsValuePayload2); + arrayResult.push(jsValue); + } + arrayResult.reverse(); + for (const cleanup of arrayCleanups) { cleanup(); } + return arrayResult; + }, + roundTripOptionalJSValueArray: function bjs_roundTripOptionalJSValueArray(values) { + const isSome = values != null; + const valuesCleanups = []; + if (isSome) { + const arrayCleanups = []; + for (const elem of values) { + const [elemKind, elemPayload1, elemPayload2] = __bjs_jsValueLower(elem); + i32Stack.push(elemKind); + i32Stack.push(elemPayload1); + f64Stack.push(elemPayload2); + } + i32Stack.push(values.length); + valuesCleanups.push(() => { for (const cleanup of arrayCleanups) { cleanup(); } }); + } + i32Stack.push(+isSome); + instance.exports.bjs_roundTripOptionalJSValueArray(); + const isSome1 = i32Stack.pop(); + let optResult; + if (isSome1) { + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const jsValuePayload2 = f64Stack.pop(); + const jsValuePayload1 = i32Stack.pop(); + const jsValueKind = i32Stack.pop(); + const jsValue = __bjs_jsValueLift(jsValueKind, jsValuePayload1, jsValuePayload2); + arrayResult.push(jsValue); + } + arrayResult.reverse(); + optResult = arrayResult; + } else { + optResult = null; + } + for (const cleanup of valuesCleanups) { cleanup(); } + return optResult; + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.d.ts similarity index 81% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.d.ts rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.d.ts index fd376d57b..7b4cc95e6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.d.ts @@ -11,15 +11,16 @@ export interface SwiftHeapObject { /// Note: Calling this method will release the heap object and it will no longer be accessible. release(): void; } -export interface Greeter extends SwiftHeapObject { +export interface GlobalClass extends SwiftHeapObject { greet(): string; - changeName(name: string): void; } export type Exports = { - Greeter: { - new(name: string): Greeter; - } - takeGreeter(greeter: Greeter): void; + GlobalAPI: { + GlobalClass: { + new(): GlobalClass; + } + globalFunction(): string; + }, } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js new file mode 100644 index 000000000..900d9b19c --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js @@ -0,0 +1,278 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_GlobalClass_wrap"] = function(pointer) { + const obj = _exports['GlobalClass'].__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; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class GlobalClass extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_GlobalClass_deinit, GlobalClass.prototype); + } + + constructor() { + const ret = instance.exports.bjs_GlobalClass_init(); + return GlobalClass.__construct(ret); + } + greet() { + instance.exports.bjs_GlobalClass_greet(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + } + const exports = { + GlobalAPI: { + GlobalClass, + globalFunction: function bjs_GlobalAPI_globalFunction() { + instance.exports.bjs_GlobalAPI_globalFunction(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.d.ts new file mode 100644 index 000000000..6f18e53ed --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.d.ts @@ -0,0 +1,54 @@ +// 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 {}; + +declare global { + namespace GlobalAPI { + class GlobalClass { + constructor(); + greet(): string; + } + function globalFunction(): string; + } +} + +/// 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 GlobalClass extends SwiftHeapObject { + greet(): string; +} +export interface PrivateClass extends SwiftHeapObject { + greet(): string; +} +export type Exports = { + GlobalAPI: { + GlobalClass: { + new(): GlobalClass; + } + globalFunction(): string; + }, + PrivateAPI: { + PrivateClass: { + new(): PrivateClass; + } + privateFunction(): string; + }, +} +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/MixedModules.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js new file mode 100644 index 000000000..9b5f9267e --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js @@ -0,0 +1,316 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: GlobalModule + if (!importObject["GlobalModule"]) { + importObject["GlobalModule"] = {}; + } + importObject["GlobalModule"]["bjs_GlobalClass_wrap"] = function(pointer) { + const obj = _exports['GlobalClass'].__construct(pointer); + return swift.memory.retain(obj); + }; + // Wrapper functions for module: PrivateModule + if (!importObject["PrivateModule"]) { + importObject["PrivateModule"] = {}; + } + importObject["PrivateModule"]["bjs_PrivateClass_wrap"] = function(pointer) { + const obj = _exports['PrivateClass'].__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; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class GlobalClass extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_GlobalClass_deinit, GlobalClass.prototype); + } + + constructor() { + const ret = instance.exports.bjs_GlobalClass_init(); + return GlobalClass.__construct(ret); + } + greet() { + instance.exports.bjs_GlobalClass_greet(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + } + class PrivateClass extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_PrivateClass_deinit, PrivateClass.prototype); + } + + constructor() { + const ret = instance.exports.bjs_PrivateClass_init(); + return PrivateClass.__construct(ret); + } + greet() { + instance.exports.bjs_PrivateClass_greet(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + } + if (typeof globalThis.GlobalAPI === 'undefined') { + globalThis.GlobalAPI = {}; + } + const exports = { + GlobalAPI: { + GlobalClass, + globalFunction: function bjs_GlobalAPI_globalFunction() { + instance.exports.bjs_GlobalAPI_globalFunction(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + }, + PrivateAPI: { + PrivateClass, + privateFunction: function bjs_PrivateAPI_privateFunction() { + instance.exports.bjs_PrivateAPI_privateFunction(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + }, + }; + _exports = exports; + globalThis.GlobalAPI.GlobalClass = exports.GlobalAPI.GlobalClass; + globalThis.GlobalAPI.globalFunction = exports.GlobalAPI.globalFunction; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.d.ts new file mode 100644 index 000000000..193857072 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.d.ts @@ -0,0 +1,33 @@ +// 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`. + +/// 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 PrivateClass extends SwiftHeapObject { + greet(): string; +} +export type Exports = { + PrivateAPI: { + PrivateClass: { + new(): PrivateClass; + } + privateFunction(): string; + }, +} +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/MixedPrivate.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js new file mode 100644 index 000000000..1ab3809cc --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js @@ -0,0 +1,278 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_PrivateClass_wrap"] = function(pointer) { + const obj = _exports['PrivateClass'].__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; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class PrivateClass extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_PrivateClass_deinit, PrivateClass.prototype); + } + + constructor() { + const ret = instance.exports.bjs_PrivateClass_init(); + return PrivateClass.__construct(ret); + } + greet() { + instance.exports.bjs_PrivateClass_greet(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + } + const exports = { + PrivateAPI: { + PrivateClass, + privateFunction: function bjs_PrivateAPI_privateFunction() { + instance.exports.bjs_PrivateAPI_privateFunction(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.d.ts deleted file mode 100644 index 83fe3c141..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.d.ts +++ /dev/null @@ -1,36 +0,0 @@ -// 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 DatabaseConnection { - connect(url: string): void; - execute(query: string): any; - readonly isConnected: boolean; - connectionTimeout: number; -} -export interface Logger { - log(message: string): void; - error(message: string, error: any): void; - readonly level: string; -} -export interface ConfigManager { - get(key: string): any; - set(key: string, value: any): void; - readonly configPath: string; -} -export type Exports = { -} -export type Imports = { - createDatabaseConnection(config: any): DatabaseConnection; - createLogger(level: string): Logger; - getConfigManager(): ConfigManager; -} -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/MultipleImportedTypes.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js deleted file mode 100644 index 394d996b6..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js +++ /dev/null @@ -1,202 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_createDatabaseConnection"] = function bjs_createDatabaseConnection(config) { - try { - let ret = imports.createDatabaseConnection(swift.memory.getObject(config)); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_createLogger"] = function bjs_createLogger(level) { - try { - const levelObject = swift.memory.getObject(level); - swift.memory.release(level); - let ret = imports.createLogger(levelObject); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_getConfigManager"] = function bjs_getConfigManager() { - try { - let ret = imports.getConfigManager(); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_DatabaseConnection_isConnected_get"] = function bjs_DatabaseConnection_isConnected_get(self) { - try { - let ret = swift.memory.getObject(self).isConnected; - return ret !== 0; - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_DatabaseConnection_connectionTimeout_get"] = function bjs_DatabaseConnection_connectionTimeout_get(self) { - try { - let ret = swift.memory.getObject(self).connectionTimeout; - return ret; - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_DatabaseConnection_connectionTimeout_set"] = function bjs_DatabaseConnection_connectionTimeout_set(self, newValue) { - try { - swift.memory.getObject(self).connectionTimeout = newValue; - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_DatabaseConnection_connect"] = function bjs_DatabaseConnection_connect(self, url) { - try { - const urlObject = swift.memory.getObject(url); - swift.memory.release(url); - swift.memory.getObject(self).connect(urlObject); - } catch (error) { - setException(error); - } - } - TestModule["bjs_DatabaseConnection_execute"] = function bjs_DatabaseConnection_execute(self, query) { - try { - const queryObject = swift.memory.getObject(query); - swift.memory.release(query); - let ret = swift.memory.getObject(self).execute(queryObject); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_Logger_level_get"] = function bjs_Logger_level_get(self) { - try { - let ret = swift.memory.getObject(self).level; - tmpRetBytes = textEncoder.encode(ret); - return tmpRetBytes.length; - } catch (error) { - setException(error); - } - } - TestModule["bjs_Logger_log"] = function bjs_Logger_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_Logger_error"] = function bjs_Logger_error(self, message, error) { - try { - const messageObject = swift.memory.getObject(message); - swift.memory.release(message); - swift.memory.getObject(self).error(messageObject, swift.memory.getObject(error)); - } catch (error) { - setException(error); - } - } - TestModule["bjs_ConfigManager_configPath_get"] = function bjs_ConfigManager_configPath_get(self) { - try { - let ret = swift.memory.getObject(self).configPath; - tmpRetBytes = textEncoder.encode(ret); - return tmpRetBytes.length; - } catch (error) { - setException(error); - } - } - TestModule["bjs_ConfigManager_get"] = function bjs_ConfigManager_get(self, key) { - try { - const keyObject = swift.memory.getObject(key); - swift.memory.release(key); - let ret = swift.memory.getObject(self).get(keyObject); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_ConfigManager_set"] = function bjs_ConfigManager_set(self, key, value) { - try { - const keyObject = swift.memory.getObject(key); - swift.memory.release(key); - swift.memory.getObject(self).set(keyObject, swift.memory.getObject(value)); - } 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; - - return { - - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js deleted file mode 100644 index 6915a61a5..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js +++ /dev/null @@ -1,192 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - // Wrapper functions for module: TestModule - if (!importObject["TestModule"]) { - importObject["TestModule"] = {}; - } - importObject["TestModule"]["bjs_Greeter_wrap"] = function(pointer) { - const obj = Greeter.__construct(pointer); - return swift.memory.retain(obj); - }; - importObject["TestModule"]["bjs_Converter_wrap"] = function(pointer) { - const obj = Converter.__construct(pointer); - return swift.memory.retain(obj); - }; - importObject["TestModule"]["bjs_UUID_wrap"] = function(pointer) { - const obj = UUID.__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 Greeter extends SwiftHeapObject { - static __construct(ptr) { - return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Greeter_deinit, Greeter.prototype); - } - - - constructor(name) { - const nameBytes = textEncoder.encode(name); - const nameId = swift.memory.retain(nameBytes); - const ret = instance.exports.bjs_Greeter_init(nameId, nameBytes.length); - swift.memory.release(nameId); - return Greeter.__construct(ret); - } - greet() { - instance.exports.bjs_Greeter_greet(this.pointer); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } - } - class Converter extends SwiftHeapObject { - static __construct(ptr) { - return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Converter_deinit, Converter.prototype); - } - - - constructor() { - const ret = instance.exports.bjs_Converter_init(); - return Converter.__construct(ret); - } - toString(value) { - instance.exports.bjs_Converter_toString(this.pointer, value); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } - } - class UUID extends SwiftHeapObject { - static __construct(ptr) { - return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_UUID_deinit, UUID.prototype); - } - - uuidString() { - instance.exports.bjs_UUID_uuidString(this.pointer); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } - } - const exports = { - Greeter, - Converter, - UUID, - plainFunction: function bjs_plainFunction() { - instance.exports.bjs_plainFunction(); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - }, - namespacedFunction: function bjs_namespacedFunction() { - instance.exports.bjs_namespacedFunction(); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - }, - }; - - if (typeof globalThis.MyModule === 'undefined') { - globalThis.MyModule = {}; - } - if (typeof globalThis.MyModule.Utils === 'undefined') { - globalThis.MyModule.Utils = {}; - } - if (typeof globalThis.Utils === 'undefined') { - globalThis.Utils = {}; - } - if (typeof globalThis.Utils.Converters === 'undefined') { - globalThis.Utils.Converters = {}; - } - if (typeof globalThis.__Swift === 'undefined') { - globalThis.__Swift = {}; - } - if (typeof globalThis.__Swift.Foundation === 'undefined') { - globalThis.__Swift.Foundation = {}; - } - globalThis.__Swift.Foundation.Greeter = exports.Greeter; - globalThis.Utils.Converters.Converter = exports.Converter; - globalThis.__Swift.Foundation.UUID = exports.UUID; - globalThis.MyModule.Utils.namespacedFunction = exports.namespacedFunction; - - return exports; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.d.ts similarity index 81% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.d.ts rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.d.ts index b2ccecc41..77d9cc0e9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.d.ts @@ -7,6 +7,11 @@ export {}; declare global { + namespace MyModule { + namespace Utils { + function namespacedFunction(): string; + } + } namespace Utils { namespace Converters { class Converter { @@ -26,11 +31,6 @@ declare global { } } } - namespace MyModule { - namespace Utils { - function namespacedFunction(): string; - } - } } /// Represents a Swift heap object like a class instance or an actor instance. @@ -50,16 +50,28 @@ export interface UUID extends SwiftHeapObject { uuidString(): string; } export type Exports = { - Greeter: { - new(name: string): Greeter; - } - Converter: { - new(): Converter; - } - UUID: { - } plainFunction(): string; - namespacedFunction(): string; + MyModule: { + Utils: { + namespacedFunction(): string; + }, + }, + Utils: { + Converters: { + Converter: { + new(): Converter; + } + }, + }, + __Swift: { + Foundation: { + Greeter: { + new(name: string): Greeter; + } + UUID: { + } + }, + }, } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js new file mode 100644 index 000000000..ea5902783 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js @@ -0,0 +1,356 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_Converter_wrap"] = function(pointer) { + const obj = _exports['Converter'].__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_Greeter_wrap"] = function(pointer) { + const obj = _exports['Greeter'].__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_UUID_wrap"] = function(pointer) { + const obj = _exports['UUID'].__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; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class Greeter extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Greeter_deinit, Greeter.prototype); + } + + constructor(name) { + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + const ret = instance.exports.bjs_Greeter_init(nameId, nameBytes.length); + return Greeter.__construct(ret); + } + greet() { + instance.exports.bjs_Greeter_greet(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + } + class Converter extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Converter_deinit, Converter.prototype); + } + + constructor() { + const ret = instance.exports.bjs_Converter_init(); + return Converter.__construct(ret); + } + toString(value) { + instance.exports.bjs_Converter_toString(this.pointer, value); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + } + class UUID extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_UUID_deinit, UUID.prototype); + } + + uuidString() { + instance.exports.bjs_UUID_uuidString(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + } + if (typeof globalThis.MyModule === 'undefined') { + globalThis.MyModule = {}; + } + if (typeof globalThis.MyModule.Utils === 'undefined') { + globalThis.MyModule.Utils = {}; + } + if (typeof globalThis.Utils === 'undefined') { + globalThis.Utils = {}; + } + if (typeof globalThis.Utils.Converters === 'undefined') { + globalThis.Utils.Converters = {}; + } + if (typeof globalThis.__Swift === 'undefined') { + globalThis.__Swift = {}; + } + if (typeof globalThis.__Swift.Foundation === 'undefined') { + globalThis.__Swift.Foundation = {}; + } + const exports = { + plainFunction: function bjs_plainFunction() { + instance.exports.bjs_plainFunction(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + MyModule: { + Utils: { + namespacedFunction: function bjs_MyModule_Utils_namespacedFunction() { + instance.exports.bjs_MyModule_Utils_namespacedFunction(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + }, + }, + Utils: { + Converters: { + Converter, + }, + }, + __Swift: { + Foundation: { + Greeter, + UUID, + }, + }, + }; + _exports = exports; + globalThis.__Swift.Foundation.Greeter = exports.__Swift.Foundation.Greeter; + globalThis.Utils.Converters.Converter = exports.Utils.Converters.Converter; + globalThis.__Swift.Foundation.UUID = exports.__Swift.Foundation.UUID; + globalThis.MyModule.Utils.namespacedFunction = exports.MyModule.Utils.namespacedFunction; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.d.ts new file mode 100644 index 000000000..67a89533a --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.d.ts @@ -0,0 +1,55 @@ +// 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`. + +/// 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 Greeter extends SwiftHeapObject { + greet(): string; +} +export interface Converter extends SwiftHeapObject { + toString(value: number): string; +} +export interface UUID extends SwiftHeapObject { + uuidString(): string; +} +export type Exports = { + plainFunction(): string; + MyModule: { + Utils: { + namespacedFunction(): string; + }, + }, + Utils: { + Converters: { + Converter: { + new(): Converter; + } + }, + }, + __Swift: { + Foundation: { + Greeter: { + new(name: string): Greeter; + } + UUID: { + } + }, + }, +} +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/Namespaces.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js new file mode 100644 index 000000000..5930b6914 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js @@ -0,0 +1,334 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_Converter_wrap"] = function(pointer) { + const obj = _exports['Converter'].__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_Greeter_wrap"] = function(pointer) { + const obj = _exports['Greeter'].__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_UUID_wrap"] = function(pointer) { + const obj = _exports['UUID'].__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; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class Greeter extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Greeter_deinit, Greeter.prototype); + } + + constructor(name) { + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + const ret = instance.exports.bjs_Greeter_init(nameId, nameBytes.length); + return Greeter.__construct(ret); + } + greet() { + instance.exports.bjs_Greeter_greet(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + } + class Converter extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Converter_deinit, Converter.prototype); + } + + constructor() { + const ret = instance.exports.bjs_Converter_init(); + return Converter.__construct(ret); + } + toString(value) { + instance.exports.bjs_Converter_toString(this.pointer, value); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + } + class UUID extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_UUID_deinit, UUID.prototype); + } + + uuidString() { + instance.exports.bjs_UUID_uuidString(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + } + const exports = { + plainFunction: function bjs_plainFunction() { + instance.exports.bjs_plainFunction(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + MyModule: { + Utils: { + namespacedFunction: function bjs_MyModule_Utils_namespacedFunction() { + instance.exports.bjs_MyModule_Utils_namespacedFunction(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + }, + }, + Utils: { + Converters: { + Converter, + }, + }, + __Swift: { + Foundation: { + Greeter, + UUID, + }, + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.d.ts new file mode 100644 index 000000000..b1a67ccde --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.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`. + +/// 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 Greeter extends SwiftHeapObject { + greet(): string; + changeName(name: string | null): void; + name: string | null; +} +export interface OptionalPropertyHolder extends SwiftHeapObject { + optionalName: string | null; + optionalAge: number | null; + optionalGreeter: Greeter | null; +} +export interface WithOptionalJSClass { + roundTripStringOrNull(value: string | null): string | null; + roundTripStringOrUndefined(value: string | undefined): string | undefined; + roundTripDoubleOrNull(value: number | null): number | null; + roundTripDoubleOrUndefined(value: number | undefined): number | undefined; + roundTripBoolOrNull(value: boolean | null): boolean | null; + roundTripBoolOrUndefined(value: boolean | undefined): boolean | undefined; + roundTripIntOrNull(value: number | null): number | null; + roundTripIntOrUndefined(value: number | undefined): number | undefined; + stringOrNull: string | null; + stringOrUndefined: string | undefined; + doubleOrNull: number | null; + doubleOrUndefined: number | undefined; + boolOrNull: boolean | null; + boolOrUndefined: boolean | undefined; + intOrNull: number | null; + intOrUndefined: number | undefined; +} +export type Exports = { + Greeter: { + new(name: string | null): Greeter; + } + OptionalPropertyHolder: { + new(): OptionalPropertyHolder; + } + roundTripOptionalClass(value: Greeter | null): Greeter | null; + testOptionalPropertyRoundtrip(holder: OptionalPropertyHolder | null): OptionalPropertyHolder | null; + roundTripString(name: string | null): string | null; + roundTripInt(value: number | null): number | null; + roundTripBool(flag: boolean | null): boolean | null; + roundTripFloat(number: number | null): number | null; + roundTripDouble(precision: number | null): number | null; + roundTripSyntax(name: string | null): string | null; + roundTripMixSyntax(name: string | null): string | null; + roundTripSwiftSyntax(name: string | null): string | null; + roundTripMixedSwiftSyntax(name: string | null): string | null; + roundTripWithSpaces(value: number | null): number | null; + roundTripAlias(age: number | null): number | null; + roundTripOptionalAlias(name: string | null): string | null; + testMixedOptionals(firstName: string | null, lastName: string | null, age: number | null, active: boolean): string | null; +} +export type Imports = { + WithOptionalJSClass: { + new(valueOrNull: string | null, valueOrUndefined: string | undefined): WithOptionalJSClass; + } +} +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/Optionals.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js new file mode 100644 index 000000000..4c0bd0d13 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js @@ -0,0 +1,756 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_Greeter_wrap"] = function(pointer) { + const obj = _exports['Greeter'].__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_OptionalPropertyHolder_wrap"] = function(pointer) { + const obj = _exports['OptionalPropertyHolder'].__construct(pointer); + return swift.memory.retain(obj); + }; + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_WithOptionalJSClass_init"] = function bjs_WithOptionalJSClass_init(valueOrNullIsSome, valueOrNullWrappedValue, valueOrUndefinedIsSome, valueOrUndefinedWrappedValue) { + try { + let obj; + if (valueOrNullIsSome) { + obj = swift.memory.getObject(valueOrNullWrappedValue); + swift.memory.release(valueOrNullWrappedValue); + } + let obj1; + if (valueOrUndefinedIsSome) { + obj1 = swift.memory.getObject(valueOrUndefinedWrappedValue); + swift.memory.release(valueOrUndefinedWrappedValue); + } + return swift.memory.retain(new imports.WithOptionalJSClass(valueOrNullIsSome ? obj : null, valueOrUndefinedIsSome ? obj1 : undefined)); + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_WithOptionalJSClass_stringOrNull_get"] = function bjs_WithOptionalJSClass_stringOrNull_get(self) { + try { + let ret = swift.memory.getObject(self).stringOrNull; + const isSome = ret != null; + if (isSome) { + tmpRetString = ret; + } else { + tmpRetString = null; + } + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_stringOrUndefined_get"] = function bjs_WithOptionalJSClass_stringOrUndefined_get(self) { + try { + let ret = swift.memory.getObject(self).stringOrUndefined; + const isSome = ret !== undefined; + if (isSome) { + tmpRetString = ret; + } else { + tmpRetString = null; + } + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_doubleOrNull_get"] = function bjs_WithOptionalJSClass_doubleOrNull_get(self) { + try { + let ret = swift.memory.getObject(self).doubleOrNull; + const isSome = ret != null; + bjs["swift_js_return_optional_double"](isSome ? 1 : 0, isSome ? ret : 0.0); + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_doubleOrUndefined_get"] = function bjs_WithOptionalJSClass_doubleOrUndefined_get(self) { + try { + let ret = swift.memory.getObject(self).doubleOrUndefined; + const isSome = ret !== undefined; + bjs["swift_js_return_optional_double"](isSome ? 1 : 0, isSome ? ret : 0.0); + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_boolOrNull_get"] = function bjs_WithOptionalJSClass_boolOrNull_get(self) { + try { + let ret = swift.memory.getObject(self).boolOrNull; + const isSome = ret != null; + bjs["swift_js_return_optional_bool"](isSome ? 1 : 0, isSome ? (ret ? 1 : 0) : 0); + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_boolOrUndefined_get"] = function bjs_WithOptionalJSClass_boolOrUndefined_get(self) { + try { + let ret = swift.memory.getObject(self).boolOrUndefined; + const isSome = ret !== undefined; + bjs["swift_js_return_optional_bool"](isSome ? 1 : 0, isSome ? (ret ? 1 : 0) : 0); + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_intOrNull_get"] = function bjs_WithOptionalJSClass_intOrNull_get(self) { + try { + let ret = swift.memory.getObject(self).intOrNull; + const isSome = ret != null; + bjs["swift_js_return_optional_int"](isSome ? 1 : 0, isSome ? (ret | 0) : 0); + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_intOrUndefined_get"] = function bjs_WithOptionalJSClass_intOrUndefined_get(self) { + try { + let ret = swift.memory.getObject(self).intOrUndefined; + const isSome = ret !== undefined; + bjs["swift_js_return_optional_int"](isSome ? 1 : 0, isSome ? (ret | 0) : 0); + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_stringOrNull_set"] = function bjs_WithOptionalJSClass_stringOrNull_set(self, newValueIsSome, newValueWrappedValue) { + try { + let obj; + if (newValueIsSome) { + obj = swift.memory.getObject(newValueWrappedValue); + swift.memory.release(newValueWrappedValue); + } + swift.memory.getObject(self).stringOrNull = newValueIsSome ? obj : null; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_stringOrUndefined_set"] = function bjs_WithOptionalJSClass_stringOrUndefined_set(self, newValueIsSome, newValueWrappedValue) { + try { + let obj; + if (newValueIsSome) { + obj = swift.memory.getObject(newValueWrappedValue); + swift.memory.release(newValueWrappedValue); + } + swift.memory.getObject(self).stringOrUndefined = newValueIsSome ? obj : undefined; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_doubleOrNull_set"] = function bjs_WithOptionalJSClass_doubleOrNull_set(self, newValueIsSome, newValueWrappedValue) { + try { + swift.memory.getObject(self).doubleOrNull = newValueIsSome ? newValueWrappedValue : null; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_doubleOrUndefined_set"] = function bjs_WithOptionalJSClass_doubleOrUndefined_set(self, newValueIsSome, newValueWrappedValue) { + try { + swift.memory.getObject(self).doubleOrUndefined = newValueIsSome ? newValueWrappedValue : undefined; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_boolOrNull_set"] = function bjs_WithOptionalJSClass_boolOrNull_set(self, newValueIsSome, newValueWrappedValue) { + try { + swift.memory.getObject(self).boolOrNull = newValueIsSome ? newValueWrappedValue !== 0 : null; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_boolOrUndefined_set"] = function bjs_WithOptionalJSClass_boolOrUndefined_set(self, newValueIsSome, newValueWrappedValue) { + try { + swift.memory.getObject(self).boolOrUndefined = newValueIsSome ? newValueWrappedValue !== 0 : undefined; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_intOrNull_set"] = function bjs_WithOptionalJSClass_intOrNull_set(self, newValueIsSome, newValueWrappedValue) { + try { + swift.memory.getObject(self).intOrNull = newValueIsSome ? newValueWrappedValue : null; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_intOrUndefined_set"] = function bjs_WithOptionalJSClass_intOrUndefined_set(self, newValueIsSome, newValueWrappedValue) { + try { + swift.memory.getObject(self).intOrUndefined = newValueIsSome ? newValueWrappedValue : undefined; + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_roundTripStringOrNull"] = function bjs_WithOptionalJSClass_roundTripStringOrNull(self, valueIsSome, valueWrappedValue) { + try { + let obj; + if (valueIsSome) { + obj = swift.memory.getObject(valueWrappedValue); + swift.memory.release(valueWrappedValue); + } + let ret = swift.memory.getObject(self).roundTripStringOrNull(valueIsSome ? obj : null); + const isSome = ret != null; + if (isSome) { + tmpRetString = ret; + } else { + tmpRetString = null; + } + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_roundTripStringOrUndefined"] = function bjs_WithOptionalJSClass_roundTripStringOrUndefined(self, valueIsSome, valueWrappedValue) { + try { + let obj; + if (valueIsSome) { + obj = swift.memory.getObject(valueWrappedValue); + swift.memory.release(valueWrappedValue); + } + let ret = swift.memory.getObject(self).roundTripStringOrUndefined(valueIsSome ? obj : undefined); + const isSome = ret !== undefined; + if (isSome) { + tmpRetString = ret; + } else { + tmpRetString = null; + } + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_roundTripDoubleOrNull"] = function bjs_WithOptionalJSClass_roundTripDoubleOrNull(self, valueIsSome, valueWrappedValue) { + try { + let ret = swift.memory.getObject(self).roundTripDoubleOrNull(valueIsSome ? valueWrappedValue : null); + const isSome = ret != null; + bjs["swift_js_return_optional_double"](isSome ? 1 : 0, isSome ? ret : 0.0); + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_roundTripDoubleOrUndefined"] = function bjs_WithOptionalJSClass_roundTripDoubleOrUndefined(self, valueIsSome, valueWrappedValue) { + try { + let ret = swift.memory.getObject(self).roundTripDoubleOrUndefined(valueIsSome ? valueWrappedValue : undefined); + const isSome = ret !== undefined; + bjs["swift_js_return_optional_double"](isSome ? 1 : 0, isSome ? ret : 0.0); + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_roundTripBoolOrNull"] = function bjs_WithOptionalJSClass_roundTripBoolOrNull(self, valueIsSome, valueWrappedValue) { + try { + let ret = swift.memory.getObject(self).roundTripBoolOrNull(valueIsSome ? valueWrappedValue !== 0 : null); + const isSome = ret != null; + bjs["swift_js_return_optional_bool"](isSome ? 1 : 0, isSome ? (ret ? 1 : 0) : 0); + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_roundTripBoolOrUndefined"] = function bjs_WithOptionalJSClass_roundTripBoolOrUndefined(self, valueIsSome, valueWrappedValue) { + try { + let ret = swift.memory.getObject(self).roundTripBoolOrUndefined(valueIsSome ? valueWrappedValue !== 0 : undefined); + const isSome = ret !== undefined; + bjs["swift_js_return_optional_bool"](isSome ? 1 : 0, isSome ? (ret ? 1 : 0) : 0); + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_roundTripIntOrNull"] = function bjs_WithOptionalJSClass_roundTripIntOrNull(self, valueIsSome, valueWrappedValue) { + try { + let ret = swift.memory.getObject(self).roundTripIntOrNull(valueIsSome ? valueWrappedValue : null); + const isSome = ret != null; + bjs["swift_js_return_optional_int"](isSome ? 1 : 0, isSome ? (ret | 0) : 0); + } catch (error) { + setException(error); + } + } + TestModule["bjs_WithOptionalJSClass_roundTripIntOrUndefined"] = function bjs_WithOptionalJSClass_roundTripIntOrUndefined(self, valueIsSome, valueWrappedValue) { + try { + let ret = swift.memory.getObject(self).roundTripIntOrUndefined(valueIsSome ? valueWrappedValue : undefined); + const isSome = ret !== undefined; + bjs["swift_js_return_optional_int"](isSome ? 1 : 0, isSome ? (ret | 0) : 0); + } 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 swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class Greeter extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Greeter_deinit, Greeter.prototype); + } + + constructor(name) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + const ret = instance.exports.bjs_Greeter_init(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + return Greeter.__construct(ret); + } + greet() { + instance.exports.bjs_Greeter_greet(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + changeName(name) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + instance.exports.bjs_Greeter_changeName(this.pointer, +isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + } + get name() { + instance.exports.bjs_Greeter_name_get(this.pointer); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + } + set name(value) { + const isSome = value != null; + let valueId, valueBytes; + if (isSome) { + valueBytes = textEncoder.encode(value); + valueId = swift.memory.retain(valueBytes); + } + instance.exports.bjs_Greeter_name_set(this.pointer, +isSome, isSome ? valueId : 0, isSome ? valueBytes.length : 0); + } + } + class OptionalPropertyHolder extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_OptionalPropertyHolder_deinit, OptionalPropertyHolder.prototype); + } + + constructor() { + const ret = instance.exports.bjs_OptionalPropertyHolder_init(); + return OptionalPropertyHolder.__construct(ret); + } + get optionalName() { + instance.exports.bjs_OptionalPropertyHolder_optionalName_get(this.pointer); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + } + set optionalName(value) { + const isSome = value != null; + let valueId, valueBytes; + if (isSome) { + valueBytes = textEncoder.encode(value); + valueId = swift.memory.retain(valueBytes); + } + instance.exports.bjs_OptionalPropertyHolder_optionalName_set(this.pointer, +isSome, isSome ? valueId : 0, isSome ? valueBytes.length : 0); + } + get optionalAge() { + instance.exports.bjs_OptionalPropertyHolder_optionalAge_get(this.pointer); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + } + set optionalAge(value) { + const isSome = value != null; + instance.exports.bjs_OptionalPropertyHolder_optionalAge_set(this.pointer, +isSome, isSome ? value : 0); + } + get optionalGreeter() { + instance.exports.bjs_OptionalPropertyHolder_optionalGreeter_get(this.pointer); + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + const optResult = pointer === null ? null : Greeter.__construct(pointer); + return optResult; + } + set optionalGreeter(value) { + const isSome = value != null; + instance.exports.bjs_OptionalPropertyHolder_optionalGreeter_set(this.pointer, +isSome, isSome ? value.pointer : 0); + } + } + const exports = { + Greeter, + OptionalPropertyHolder, + roundTripOptionalClass: function bjs_roundTripOptionalClass(value) { + const isSome = value != null; + instance.exports.bjs_roundTripOptionalClass(+isSome, isSome ? value.pointer : 0); + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + const optResult = pointer === null ? null : Greeter.__construct(pointer); + return optResult; + }, + testOptionalPropertyRoundtrip: function bjs_testOptionalPropertyRoundtrip(holder) { + const isSome = holder != null; + instance.exports.bjs_testOptionalPropertyRoundtrip(+isSome, isSome ? holder.pointer : 0); + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + const optResult = pointer === null ? null : OptionalPropertyHolder.__construct(pointer); + return optResult; + }, + roundTripString: function bjs_roundTripString(name) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + instance.exports.bjs_roundTripString(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + }, + roundTripInt: function bjs_roundTripInt(value) { + const isSome = value != null; + instance.exports.bjs_roundTripInt(+isSome, isSome ? value : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, + roundTripBool: function bjs_roundTripBool(flag) { + const isSome = flag != null; + instance.exports.bjs_roundTripBool(+isSome, isSome ? flag : 0); + const optResult = tmpRetOptionalBool; + tmpRetOptionalBool = undefined; + return optResult; + }, + roundTripFloat: function bjs_roundTripFloat(number) { + const isSome = number != null; + instance.exports.bjs_roundTripFloat(+isSome, isSome ? number : 0); + const optResult = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; + return optResult; + }, + roundTripDouble: function bjs_roundTripDouble(precision) { + const isSome = precision != null; + instance.exports.bjs_roundTripDouble(+isSome, isSome ? precision : 0); + const optResult = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + return optResult; + }, + roundTripSyntax: function bjs_roundTripSyntax(name) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + instance.exports.bjs_roundTripSyntax(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + }, + roundTripMixSyntax: function bjs_roundTripMixSyntax(name) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + instance.exports.bjs_roundTripMixSyntax(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + }, + roundTripSwiftSyntax: function bjs_roundTripSwiftSyntax(name) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + instance.exports.bjs_roundTripSwiftSyntax(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + }, + roundTripMixedSwiftSyntax: function bjs_roundTripMixedSwiftSyntax(name) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + instance.exports.bjs_roundTripMixedSwiftSyntax(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + }, + roundTripWithSpaces: function bjs_roundTripWithSpaces(value) { + const isSome = value != null; + instance.exports.bjs_roundTripWithSpaces(+isSome, isSome ? value : 0); + const optResult = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + return optResult; + }, + roundTripAlias: function bjs_roundTripAlias(age) { + const isSome = age != null; + instance.exports.bjs_roundTripAlias(+isSome, isSome ? age : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, + roundTripOptionalAlias: function bjs_roundTripOptionalAlias(name) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + instance.exports.bjs_roundTripOptionalAlias(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + }, + testMixedOptionals: function bjs_testMixedOptionals(firstName, lastName, age, active) { + const isSome = firstName != null; + let firstNameId, firstNameBytes; + if (isSome) { + firstNameBytes = textEncoder.encode(firstName); + firstNameId = swift.memory.retain(firstNameBytes); + } + const isSome1 = lastName != null; + let lastNameId, lastNameBytes; + if (isSome1) { + lastNameBytes = textEncoder.encode(lastName); + lastNameId = swift.memory.retain(lastNameBytes); + } + const isSome2 = age != null; + instance.exports.bjs_testMixedOptionals(+isSome, isSome ? firstNameId : 0, isSome ? firstNameBytes.length : 0, +isSome1, isSome1 ? lastNameId : 0, isSome1 ? lastNameBytes.length : 0, +isSome2, isSome2 ? age : 0, active); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.js deleted file mode 100644 index 4873fc33c..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.js +++ /dev/null @@ -1,73 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - - }, - 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; - - return { - check: function bjs_check(a, b, c, d) { - instance.exports.bjs_check(a, b, c, d); - }, - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js deleted file mode 100644 index 3b93b2dd0..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js +++ /dev/null @@ -1,78 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_check"] = function bjs_check(a, b) { - try { - imports.check(a, b); - } 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; - - return { - - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.d.ts similarity index 88% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.d.ts rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.d.ts index 5442ebfa2..961f97635 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.d.ts @@ -5,6 +5,7 @@ // `swift package bridge-js`. export type Exports = { + check(a: number, b: number, c: number, d: number, e: boolean): void; } export type Imports = { check(a: number, b: boolean): void; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js new file mode 100644 index 000000000..83c77397a --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js @@ -0,0 +1,228 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_check"] = function bjs_check(a, b) { + try { + imports.check(a, b !== 0); + } 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 = { + check: function bjs_check(a, b, c, d, e) { + instance.exports.bjs_check(a, b, c, d, e); + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js deleted file mode 100644 index 53332b97b..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js +++ /dev/null @@ -1,86 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - - }, - 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; - - return { - checkInt: function bjs_checkInt() { - const ret = instance.exports.bjs_checkInt(); - return ret; - }, - checkFloat: function bjs_checkFloat() { - const ret = instance.exports.bjs_checkFloat(); - return ret; - }, - checkDouble: function bjs_checkDouble() { - const ret = instance.exports.bjs_checkDouble(); - return ret; - }, - checkBool: function bjs_checkBool() { - const ret = instance.exports.bjs_checkBool() !== 0; - return ret; - }, - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.d.ts deleted file mode 100644 index ad63bd7d0..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -// 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 type Exports = { -} -export type Imports = { - checkNumber(): number; - checkBoolean(): boolean; -} -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/PrimitiveReturn.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js deleted file mode 100644 index 1892eb46e..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js +++ /dev/null @@ -1,89 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_checkNumber"] = function bjs_checkNumber() { - try { - let ret = imports.checkNumber(); - return ret; - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_checkBoolean"] = function bjs_checkBoolean() { - try { - let ret = imports.checkBoolean(); - return ret !== 0; - } catch (error) { - setException(error); - return 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; - - return { - - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.d.ts similarity index 88% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.d.ts rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.d.ts index da7f59772..77e269d16 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.d.ts @@ -6,11 +6,14 @@ export type Exports = { checkInt(): number; + checkUInt(): number; checkFloat(): number; checkDouble(): number; checkBool(): boolean; } export type Imports = { + checkNumber(): number; + checkBoolean(): boolean; } export function createInstantiator(options: { imports: Imports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js new file mode 100644 index 000000000..f1fda2cb7 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js @@ -0,0 +1,256 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_checkNumber"] = function bjs_checkNumber() { + try { + let ret = imports.checkNumber(); + return ret; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_checkBoolean"] = function bjs_checkBoolean() { + try { + let ret = imports.checkBoolean(); + return ret ? 1 : 0; + } catch (error) { + setException(error); + return 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 exports = { + checkInt: function bjs_checkInt() { + 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; + }, + checkDouble: function bjs_checkDouble() { + const ret = instance.exports.bjs_checkDouble(); + return ret; + }, + checkBool: function bjs_checkBool() { + const ret = instance.exports.bjs_checkBool(); + return ret !== 0; + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.d.ts new file mode 100644 index 000000000..8f65849ab --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.d.ts @@ -0,0 +1,48 @@ +// 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`. + +/// 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 PropertyHolder extends SwiftHeapObject { + getAllValues(): string; + intValue: number; + floatValue: number; + doubleValue: number; + boolValue: boolean; + stringValue: string; + readonly readonlyInt: number; + readonly readonlyFloat: number; + readonly readonlyDouble: number; + readonly readonlyBool: boolean; + readonly readonlyString: string; + jsObject: any; + sibling: PropertyHolder; + lazyValue: string; + readonly computedReadonly: number; + computedReadWrite: string; + observedProperty: number; +} +export type Exports = { + PropertyHolder: { + new(intValue: number, floatValue: number, doubleValue: number, boolValue: boolean, stringValue: string, jsObject: any): PropertyHolder; + } + createPropertyHolder(intValue: number, floatValue: number, doubleValue: number, boolValue: boolean, stringValue: string, jsObject: any): PropertyHolder; + testPropertyHolder(holder: PropertyHolder): string; +} +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/PropertyTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js new file mode 100644 index 000000000..e7d80bb4d --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js @@ -0,0 +1,394 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_PropertyHolder_wrap"] = function(pointer) { + const obj = _exports['PropertyHolder'].__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; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class PropertyHolder extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_PropertyHolder_deinit, PropertyHolder.prototype); + } + + constructor(intValue, floatValue, doubleValue, boolValue, stringValue, jsObject) { + const stringValueBytes = textEncoder.encode(stringValue); + const stringValueId = swift.memory.retain(stringValueBytes); + const ret = instance.exports.bjs_PropertyHolder_init(intValue, floatValue, doubleValue, boolValue, stringValueId, stringValueBytes.length, swift.memory.retain(jsObject)); + return PropertyHolder.__construct(ret); + } + getAllValues() { + instance.exports.bjs_PropertyHolder_getAllValues(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + get intValue() { + const ret = instance.exports.bjs_PropertyHolder_intValue_get(this.pointer); + return ret; + } + set intValue(value) { + instance.exports.bjs_PropertyHolder_intValue_set(this.pointer, value); + } + get floatValue() { + const ret = instance.exports.bjs_PropertyHolder_floatValue_get(this.pointer); + return ret; + } + set floatValue(value) { + instance.exports.bjs_PropertyHolder_floatValue_set(this.pointer, value); + } + get doubleValue() { + const ret = instance.exports.bjs_PropertyHolder_doubleValue_get(this.pointer); + return ret; + } + set doubleValue(value) { + instance.exports.bjs_PropertyHolder_doubleValue_set(this.pointer, value); + } + get boolValue() { + const ret = instance.exports.bjs_PropertyHolder_boolValue_get(this.pointer); + return ret !== 0; + } + set boolValue(value) { + instance.exports.bjs_PropertyHolder_boolValue_set(this.pointer, value); + } + get stringValue() { + instance.exports.bjs_PropertyHolder_stringValue_get(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + set stringValue(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyHolder_stringValue_set(this.pointer, valueId, valueBytes.length); + } + get readonlyInt() { + const ret = instance.exports.bjs_PropertyHolder_readonlyInt_get(this.pointer); + return ret; + } + get readonlyFloat() { + const ret = instance.exports.bjs_PropertyHolder_readonlyFloat_get(this.pointer); + return ret; + } + get readonlyDouble() { + const ret = instance.exports.bjs_PropertyHolder_readonlyDouble_get(this.pointer); + return ret; + } + get readonlyBool() { + const ret = instance.exports.bjs_PropertyHolder_readonlyBool_get(this.pointer); + return ret !== 0; + } + get readonlyString() { + instance.exports.bjs_PropertyHolder_readonlyString_get(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + get jsObject() { + const ret = instance.exports.bjs_PropertyHolder_jsObject_get(this.pointer); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + } + set jsObject(value) { + instance.exports.bjs_PropertyHolder_jsObject_set(this.pointer, swift.memory.retain(value)); + } + get sibling() { + const ret = instance.exports.bjs_PropertyHolder_sibling_get(this.pointer); + return PropertyHolder.__construct(ret); + } + set sibling(value) { + instance.exports.bjs_PropertyHolder_sibling_set(this.pointer, value.pointer); + } + get lazyValue() { + instance.exports.bjs_PropertyHolder_lazyValue_get(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + set lazyValue(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyHolder_lazyValue_set(this.pointer, valueId, valueBytes.length); + } + get computedReadonly() { + const ret = instance.exports.bjs_PropertyHolder_computedReadonly_get(this.pointer); + return ret; + } + get computedReadWrite() { + instance.exports.bjs_PropertyHolder_computedReadWrite_get(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + set computedReadWrite(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyHolder_computedReadWrite_set(this.pointer, valueId, valueBytes.length); + } + get observedProperty() { + const ret = instance.exports.bjs_PropertyHolder_observedProperty_get(this.pointer); + return ret; + } + set observedProperty(value) { + instance.exports.bjs_PropertyHolder_observedProperty_set(this.pointer, value); + } + } + const exports = { + PropertyHolder, + createPropertyHolder: function bjs_createPropertyHolder(intValue, floatValue, doubleValue, boolValue, stringValue, jsObject) { + const stringValueBytes = textEncoder.encode(stringValue); + const stringValueId = swift.memory.retain(stringValueBytes); + const ret = instance.exports.bjs_createPropertyHolder(intValue, floatValue, doubleValue, boolValue, stringValueId, stringValueBytes.length, swift.memory.retain(jsObject)); + return PropertyHolder.__construct(ret); + }, + testPropertyHolder: function bjs_testPropertyHolder(holder) { + instance.exports.bjs_testPropertyHolder(holder.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.d.ts new file mode 100644 index 000000000..4c09ad85f --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.d.ts @@ -0,0 +1,121 @@ +// 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 MyViewControllerDelegate { + onSomethingHappened(): void; + onValueChanged(value: string): void; + onCountUpdated(count: number): boolean; + onLabelUpdated(prefix: string, suffix: string): void; + isCountEven(): boolean; + onHelperUpdated(helper: Helper): void; + createHelper(): Helper; + onOptionalHelperUpdated(helper: Helper | null): void; + createOptionalHelper(): Helper | null; + createEnum(): ExampleEnumTag; + handleResult(result: ResultTag): void; + getResult(): ResultTag; + eventCount: number; + readonly delegateName: string; + optionalName: string | null; + optionalRawEnum: ExampleEnumTag | null; + rawStringEnum: ExampleEnumTag; + result: ResultTag; + optionalResult: ResultTag | null; + direction: DirectionTag; + directionOptional: DirectionTag | null; + priority: PriorityTag; + priorityOptional: PriorityTag | null; +} + +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 ExampleEnumValues: { + readonly Test: "test"; + readonly Test2: "test2"; +}; +export type ExampleEnumTag = typeof ExampleEnumValues[keyof typeof ExampleEnumValues]; + +export const ResultValues: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + }; +}; + +export type ResultTag = + { tag: typeof ResultValues.Tag.Success; param0: string } | { tag: typeof ResultValues.Tag.Failure; param0: number } + +export const PriorityValues: { + readonly Low: -1; + readonly Medium: 0; + readonly High: 1; +}; +export type PriorityTag = typeof PriorityValues[keyof typeof PriorityValues]; + +export type DirectionObject = typeof DirectionValues; + +export type ExampleEnumObject = typeof ExampleEnumValues; + +export type ResultObject = typeof ResultValues; + +export type PriorityObject = typeof PriorityValues; + +/// 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 Helper extends SwiftHeapObject { + increment(): void; + value: number; +} +export interface MyViewController extends SwiftHeapObject { + triggerEvent(): void; + updateValue(value: string): void; + updateCount(count: number): boolean; + updateLabel(prefix: string, suffix: string): void; + checkEvenCount(): boolean; + sendHelper(helper: Helper): void; + delegate: MyViewControllerDelegate; + secondDelegate: MyViewControllerDelegate | null; +} +export interface DelegateManager extends SwiftHeapObject { + notifyAll(): void; + delegates: MyViewControllerDelegate[]; +} +export type Exports = { + Helper: { + new(value: number): Helper; + } + MyViewController: { + new(delegate: MyViewControllerDelegate): MyViewController; + } + DelegateManager: { + new(delegates: MyViewControllerDelegate[]): DelegateManager; + } + processDelegates(delegates: MyViewControllerDelegate[]): MyViewControllerDelegate[]; + Direction: DirectionObject + ExampleEnum: ExampleEnumObject + Result: ResultObject + Priority: PriorityObject +} +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/Protocol.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js new file mode 100644 index 000000000..58928211e --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js @@ -0,0 +1,762 @@ +// 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 ExampleEnumValues = { + Test: "test", + Test2: "test2", +}; + +export const ResultValues = { + Tag: { + Success: 0, + Failure: 1, + }, +}; +export const PriorityValues = { + Low: -1, + Medium: 0, + High: 1, +}; + +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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createResultValuesHelpers = () => { + return () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case ResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const cleanup = undefined; + return { caseId: ResultValues.Tag.Success, cleanup }; + } + case ResultValues.Tag.Failure: { + i32Stack.push((value.param0 | 0)); + const cleanup = undefined; + return { caseId: ResultValues.Tag.Failure, cleanup }; + } + default: throw new Error("Unknown ResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case ResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: ResultValues.Tag.Success, param0: string }; + } + case ResultValues.Tag.Failure: { + const int = i32Stack.pop(); + return { tag: ResultValues.Tag.Failure, param0: int }; + } + default: throw new Error("Unknown ResultValues tag returned from Swift: " + String(tag)); + } + } + }); + }; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_DelegateManager_wrap"] = function(pointer) { + const obj = _exports['DelegateManager'].__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_Helper_wrap"] = function(pointer) { + const obj = _exports['Helper'].__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_MyViewController_wrap"] = function(pointer) { + const obj = _exports['MyViewController'].__construct(pointer); + return swift.memory.retain(obj); + }; + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_MyViewControllerDelegate_eventCount_get"] = function bjs_MyViewControllerDelegate_eventCount_get(self) { + try { + let ret = swift.memory.getObject(self).eventCount; + return ret; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_MyViewControllerDelegate_eventCount_set"] = function bjs_MyViewControllerDelegate_eventCount_set(self, value) { + try { + swift.memory.getObject(self).eventCount = value; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_delegateName_get"] = function bjs_MyViewControllerDelegate_delegateName_get(self) { + try { + let ret = swift.memory.getObject(self).delegateName; + tmpRetBytes = textEncoder.encode(ret); + return tmpRetBytes.length; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_optionalName_get"] = function bjs_MyViewControllerDelegate_optionalName_get(self) { + try { + let ret = swift.memory.getObject(self).optionalName; + tmpRetString = ret; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_optionalName_set"] = function bjs_MyViewControllerDelegate_optionalName_set(self, valueIsSome, valueWrappedValue) { + try { + let obj; + if (valueIsSome) { + obj = swift.memory.getObject(valueWrappedValue); + swift.memory.release(valueWrappedValue); + } + swift.memory.getObject(self).optionalName = valueIsSome ? obj : null; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_optionalRawEnum_get"] = function bjs_MyViewControllerDelegate_optionalRawEnum_get(self) { + try { + let ret = swift.memory.getObject(self).optionalRawEnum; + tmpRetString = ret; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_optionalRawEnum_set"] = function bjs_MyViewControllerDelegate_optionalRawEnum_set(self, valueIsSome, valueWrappedValue) { + try { + let obj; + if (valueIsSome) { + obj = swift.memory.getObject(valueWrappedValue); + swift.memory.release(valueWrappedValue); + } + swift.memory.getObject(self).optionalRawEnum = valueIsSome ? obj : null; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_rawStringEnum_get"] = function bjs_MyViewControllerDelegate_rawStringEnum_get(self) { + try { + let ret = swift.memory.getObject(self).rawStringEnum; + tmpRetBytes = textEncoder.encode(ret); + return tmpRetBytes.length; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_rawStringEnum_set"] = function bjs_MyViewControllerDelegate_rawStringEnum_set(self, value) { + try { + const valueObject = swift.memory.getObject(value); + swift.memory.release(value); + swift.memory.getObject(self).rawStringEnum = valueObject; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_result_get"] = function bjs_MyViewControllerDelegate_result_get(self) { + try { + let ret = swift.memory.getObject(self).result; + const { caseId: caseId, cleanup: cleanup } = enumHelpers.Result.lower(ret); + return caseId; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_result_set"] = function bjs_MyViewControllerDelegate_result_set(self, value) { + try { + const enumValue = enumHelpers.Result.lift(value); + swift.memory.getObject(self).result = enumValue; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_optionalResult_get"] = function bjs_MyViewControllerDelegate_optionalResult_get(self) { + try { + let ret = swift.memory.getObject(self).optionalResult; + const isSome = ret != null; + if (isSome) { + const { caseId: caseId, cleanup: cleanup } = enumHelpers.Result.lower(ret); + return caseId; + } else { + return -1; + } + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_optionalResult_set"] = function bjs_MyViewControllerDelegate_optionalResult_set(self, valueIsSome, valueWrappedValue) { + try { + let enumValue; + if (valueIsSome) { + enumValue = enumHelpers.Result.lift(valueWrappedValue); + } + swift.memory.getObject(self).optionalResult = valueIsSome ? enumValue : null; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_direction_get"] = function bjs_MyViewControllerDelegate_direction_get(self) { + try { + let ret = swift.memory.getObject(self).direction; + return ret; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_MyViewControllerDelegate_direction_set"] = function bjs_MyViewControllerDelegate_direction_set(self, value) { + try { + swift.memory.getObject(self).direction = value; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_directionOptional_get"] = function bjs_MyViewControllerDelegate_directionOptional_get(self) { + try { + let ret = swift.memory.getObject(self).directionOptional; + const isSome = ret != null; + return isSome ? (ret | 0) : -1; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_directionOptional_set"] = function bjs_MyViewControllerDelegate_directionOptional_set(self, valueIsSome, valueWrappedValue) { + try { + swift.memory.getObject(self).directionOptional = valueIsSome ? valueWrappedValue : null; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_priority_get"] = function bjs_MyViewControllerDelegate_priority_get(self) { + try { + let ret = swift.memory.getObject(self).priority; + return ret; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_MyViewControllerDelegate_priority_set"] = function bjs_MyViewControllerDelegate_priority_set(self, value) { + try { + swift.memory.getObject(self).priority = value; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_priorityOptional_get"] = function bjs_MyViewControllerDelegate_priorityOptional_get(self) { + try { + let ret = swift.memory.getObject(self).priorityOptional; + tmpRetOptionalInt = ret; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_priorityOptional_set"] = function bjs_MyViewControllerDelegate_priorityOptional_set(self, valueIsSome, valueWrappedValue) { + try { + swift.memory.getObject(self).priorityOptional = valueIsSome ? valueWrappedValue : null; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_onSomethingHappened"] = function bjs_MyViewControllerDelegate_onSomethingHappened(self) { + try { + swift.memory.getObject(self).onSomethingHappened(); + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_onValueChanged"] = function bjs_MyViewControllerDelegate_onValueChanged(self, value) { + try { + const valueObject = swift.memory.getObject(value); + swift.memory.release(value); + swift.memory.getObject(self).onValueChanged(valueObject); + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_onCountUpdated"] = function bjs_MyViewControllerDelegate_onCountUpdated(self, count) { + try { + let ret = swift.memory.getObject(self).onCountUpdated(count); + return ret ? 1 : 0; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_MyViewControllerDelegate_onLabelUpdated"] = function bjs_MyViewControllerDelegate_onLabelUpdated(self, prefix, suffix) { + try { + const prefixObject = swift.memory.getObject(prefix); + swift.memory.release(prefix); + const suffixObject = swift.memory.getObject(suffix); + swift.memory.release(suffix); + swift.memory.getObject(self).onLabelUpdated(prefixObject, suffixObject); + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_isCountEven"] = function bjs_MyViewControllerDelegate_isCountEven(self) { + try { + let ret = swift.memory.getObject(self).isCountEven(); + return ret ? 1 : 0; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_MyViewControllerDelegate_onHelperUpdated"] = function bjs_MyViewControllerDelegate_onHelperUpdated(self, helper) { + try { + swift.memory.getObject(self).onHelperUpdated(_exports['Helper'].__construct(helper)); + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_createHelper"] = function bjs_MyViewControllerDelegate_createHelper(self) { + try { + let ret = swift.memory.getObject(self).createHelper(); + return ret.pointer; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_MyViewControllerDelegate_onOptionalHelperUpdated"] = function bjs_MyViewControllerDelegate_onOptionalHelperUpdated(self, helperIsSome, helperWrappedValue) { + try { + swift.memory.getObject(self).onOptionalHelperUpdated(helperIsSome ? _exports['Helper'].__construct(helperWrappedValue) : null); + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_createOptionalHelper"] = function bjs_MyViewControllerDelegate_createOptionalHelper(self) { + try { + let ret = swift.memory.getObject(self).createOptionalHelper(); + const isSome = ret != null; + return isSome ? ret.pointer : 0; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_createEnum"] = function bjs_MyViewControllerDelegate_createEnum(self) { + try { + let ret = swift.memory.getObject(self).createEnum(); + tmpRetBytes = textEncoder.encode(ret); + return tmpRetBytes.length; + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_handleResult"] = function bjs_MyViewControllerDelegate_handleResult(self, result) { + try { + const enumValue = enumHelpers.Result.lift(result); + swift.memory.getObject(self).handleResult(enumValue); + } catch (error) { + setException(error); + } + } + TestModule["bjs_MyViewControllerDelegate_getResult"] = function bjs_MyViewControllerDelegate_getResult(self) { + try { + let ret = swift.memory.getObject(self).getResult(); + const { caseId: caseId, cleanup: cleanup } = enumHelpers.Result.lower(ret); + return caseId; + } 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 swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class Helper extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Helper_deinit, Helper.prototype); + } + + constructor(value) { + const ret = instance.exports.bjs_Helper_init(value); + return Helper.__construct(ret); + } + increment() { + instance.exports.bjs_Helper_increment(this.pointer); + } + get value() { + const ret = instance.exports.bjs_Helper_value_get(this.pointer); + return ret; + } + set value(value) { + instance.exports.bjs_Helper_value_set(this.pointer, value); + } + } + class MyViewController extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_MyViewController_deinit, MyViewController.prototype); + } + + constructor(delegate) { + const ret = instance.exports.bjs_MyViewController_init(swift.memory.retain(delegate)); + return MyViewController.__construct(ret); + } + triggerEvent() { + instance.exports.bjs_MyViewController_triggerEvent(this.pointer); + } + updateValue(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_MyViewController_updateValue(this.pointer, valueId, valueBytes.length); + } + updateCount(count) { + const ret = instance.exports.bjs_MyViewController_updateCount(this.pointer, count); + return ret !== 0; + } + updateLabel(prefix, suffix) { + const prefixBytes = textEncoder.encode(prefix); + const prefixId = swift.memory.retain(prefixBytes); + const suffixBytes = textEncoder.encode(suffix); + const suffixId = swift.memory.retain(suffixBytes); + instance.exports.bjs_MyViewController_updateLabel(this.pointer, prefixId, prefixBytes.length, suffixId, suffixBytes.length); + } + checkEvenCount() { + const ret = instance.exports.bjs_MyViewController_checkEvenCount(this.pointer); + return ret !== 0; + } + sendHelper(helper) { + instance.exports.bjs_MyViewController_sendHelper(this.pointer, helper.pointer); + } + get delegate() { + const ret = instance.exports.bjs_MyViewController_delegate_get(this.pointer); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + } + set delegate(value) { + instance.exports.bjs_MyViewController_delegate_set(this.pointer, swift.memory.retain(value)); + } + get secondDelegate() { + instance.exports.bjs_MyViewController_secondDelegate_get(this.pointer); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + } + set secondDelegate(value) { + const isSome = value != null; + 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); + i32Stack.push(objId); + } + i32Stack.push(delegates.length); + const ret = instance.exports.bjs_DelegateManager_init(); + for (const cleanup of arrayCleanups) { cleanup(); } + return DelegateManager.__construct(ret); + } + notifyAll() { + instance.exports.bjs_DelegateManager_notifyAll(this.pointer); + } + get delegates() { + instance.exports.bjs_DelegateManager_delegates_get(this.pointer); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const objId = i32Stack.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); + i32Stack.push(objId); + } + i32Stack.push(value.length); + instance.exports.bjs_DelegateManager_delegates_set(this.pointer); + for (const cleanup of arrayCleanups) { cleanup(); } + } + } + const ResultHelpers = __bjs_createResultValuesHelpers()(); + enumHelpers.Result = ResultHelpers; + + const exports = { + Helper, + MyViewController, + DelegateManager, + processDelegates: function bjs_processDelegates(delegates) { + const arrayCleanups = []; + for (const elem of delegates) { + const objId = swift.memory.retain(elem); + i32Stack.push(objId); + } + i32Stack.push(delegates.length); + instance.exports.bjs_processDelegates(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const objId1 = i32Stack.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, + Priority: PriorityValues, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.d.ts new file mode 100644 index 000000000..a2f1c7d6d --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.d.ts @@ -0,0 +1,73 @@ +// 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 CalculatorValues: { + readonly Scientific: 0; + readonly Basic: 1; +}; +export type CalculatorTag = typeof CalculatorValues[keyof typeof CalculatorValues]; + +export const APIResultValues: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + }; +}; + +export type APIResultTag = + { tag: typeof APIResultValues.Tag.Success; param0: string } | { tag: typeof APIResultValues.Tag.Failure; param0: number } + +export type CalculatorObject = typeof CalculatorValues & { + square(value: number): number; +}; + +export type APIResultObject = typeof APIResultValues & { + roundtrip(value: APIResultTag): APIResultTag; +}; + +export {}; + +declare global { + namespace Utils { + namespace String { + function uppercase(text: string): string; + } + } +} + +/// 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 MathUtils extends SwiftHeapObject { + multiply(x: number, y: number): number; +} +export type Exports = { + MathUtils: { + new(): MathUtils; + subtract(a: number, b: number): number; + add(a: number, b: number): number; + } + Calculator: CalculatorObject + APIResult: APIResultObject + Utils: { + String: { + uppercase(text: string): string; + }, + }, +} +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/StaticFunctions.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js new file mode 100644 index 000000000..247374a3b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js @@ -0,0 +1,363 @@ +// 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 CalculatorValues = { + Scientific: 0, + Basic: 1, +}; + +export const APIResultValues = { + Tag: { + Success: 0, + Failure: 1, + }, +}; +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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createAPIResultValuesHelpers = () => { + return () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case APIResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Success, cleanup }; + } + case APIResultValues.Tag.Failure: { + i32Stack.push((value.param0 | 0)); + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Failure, cleanup }; + } + default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case APIResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: APIResultValues.Tag.Success, param0: string }; + } + case APIResultValues.Tag.Failure: { + const int = i32Stack.pop(); + return { tag: APIResultValues.Tag.Failure, param0: int }; + } + default: throw new Error("Unknown APIResultValues tag returned from Swift: " + String(tag)); + } + } + }); + }; + + return { + /** + * @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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_MathUtils_wrap"] = function(pointer) { + const obj = _exports['MathUtils'].__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; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class MathUtils extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_MathUtils_deinit, MathUtils.prototype); + } + + constructor() { + const ret = instance.exports.bjs_MathUtils_init(); + return MathUtils.__construct(ret); + } + static subtract(a, b) { + const ret = instance.exports.bjs_MathUtils_static_subtract(a, b); + return ret; + } + static add(a, b) { + const ret = instance.exports.bjs_MathUtils_static_add(a, b); + return ret; + } + multiply(x, y) { + const ret = instance.exports.bjs_MathUtils_multiply(this.pointer, x, y); + return ret; + } + } + const APIResultHelpers = __bjs_createAPIResultValuesHelpers()(); + enumHelpers.APIResult = APIResultHelpers; + + if (typeof globalThis.Utils === 'undefined') { + globalThis.Utils = {}; + } + if (typeof globalThis.Utils.String === 'undefined') { + globalThis.Utils.String = {}; + } + const exports = { + MathUtils, + Calculator: { + ...CalculatorValues, + square: function(value) { + const ret = instance.exports.bjs_Calculator_static_square(value); + return ret; + } + }, + APIResult: { + ...APIResultValues, + roundtrip: function(value) { + const { caseId: valueCaseId, cleanup: valueCleanup } = enumHelpers.APIResult.lower(value); + instance.exports.bjs_APIResult_static_roundtrip(valueCaseId); + const ret = enumHelpers.APIResult.lift(i32Stack.pop()); + if (valueCleanup) { valueCleanup(); } + return ret; + } + }, + Utils: { + String: { + uppercase: function bjs_Utils_String_static_uppercase(text) { + const textBytes = textEncoder.encode(text); + const textId = swift.memory.retain(textBytes); + instance.exports.bjs_Utils_String_static_uppercase(textId, textBytes.length); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + }, + }, + }; + _exports = exports; + globalThis.Utils.String.uppercase = exports.Utils.String.uppercase; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.d.ts new file mode 100644 index 000000000..e938ddb9a --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.d.ts @@ -0,0 +1,63 @@ +// 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 CalculatorValues: { + readonly Scientific: 0; + readonly Basic: 1; +}; +export type CalculatorTag = typeof CalculatorValues[keyof typeof CalculatorValues]; + +export const APIResultValues: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + }; +}; + +export type APIResultTag = + { tag: typeof APIResultValues.Tag.Success; param0: string } | { tag: typeof APIResultValues.Tag.Failure; param0: number } + +export type CalculatorObject = typeof CalculatorValues & { + square(value: number): number; +}; + +export type APIResultObject = typeof APIResultValues & { + roundtrip(value: APIResultTag): APIResultTag; +}; + +/// 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 MathUtils extends SwiftHeapObject { + multiply(x: number, y: number): number; +} +export type Exports = { + MathUtils: { + new(): MathUtils; + subtract(a: number, b: number): number; + add(a: number, b: number): number; + } + Calculator: CalculatorObject + APIResult: APIResultObject + Utils: { + String: { + uppercase(text: string): string; + }, + }, +} +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/StaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js new file mode 100644 index 000000000..a3bfb8a24 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js @@ -0,0 +1,356 @@ +// 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 CalculatorValues = { + Scientific: 0, + Basic: 1, +}; + +export const APIResultValues = { + Tag: { + Success: 0, + Failure: 1, + }, +}; +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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createAPIResultValuesHelpers = () => { + return () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case APIResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Success, cleanup }; + } + case APIResultValues.Tag.Failure: { + i32Stack.push((value.param0 | 0)); + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Failure, cleanup }; + } + default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case APIResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: APIResultValues.Tag.Success, param0: string }; + } + case APIResultValues.Tag.Failure: { + const int = i32Stack.pop(); + return { tag: APIResultValues.Tag.Failure, param0: int }; + } + default: throw new Error("Unknown APIResultValues tag returned from Swift: " + String(tag)); + } + } + }); + }; + + return { + /** + * @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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_MathUtils_wrap"] = function(pointer) { + const obj = _exports['MathUtils'].__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; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class MathUtils extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_MathUtils_deinit, MathUtils.prototype); + } + + constructor() { + const ret = instance.exports.bjs_MathUtils_init(); + return MathUtils.__construct(ret); + } + static subtract(a, b) { + const ret = instance.exports.bjs_MathUtils_static_subtract(a, b); + return ret; + } + static add(a, b) { + const ret = instance.exports.bjs_MathUtils_static_add(a, b); + return ret; + } + multiply(x, y) { + const ret = instance.exports.bjs_MathUtils_multiply(this.pointer, x, y); + return ret; + } + } + const APIResultHelpers = __bjs_createAPIResultValuesHelpers()(); + enumHelpers.APIResult = APIResultHelpers; + + const exports = { + MathUtils, + Calculator: { + ...CalculatorValues, + square: function(value) { + const ret = instance.exports.bjs_Calculator_static_square(value); + return ret; + } + }, + APIResult: { + ...APIResultValues, + roundtrip: function(value) { + const { caseId: valueCaseId, cleanup: valueCleanup } = enumHelpers.APIResult.lower(value); + instance.exports.bjs_APIResult_static_roundtrip(valueCaseId); + const ret = enumHelpers.APIResult.lift(i32Stack.pop()); + if (valueCleanup) { valueCleanup(); } + return ret; + } + }, + Utils: { + String: { + uppercase: function bjs_Utils_String_static_uppercase(text) { + const textBytes = textEncoder.encode(text); + const textId = swift.memory.retain(textBytes); + instance.exports.bjs_Utils_String_static_uppercase(textId, textBytes.length); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + }, + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.d.ts new file mode 100644 index 000000000..fea3c4b59 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.d.ts @@ -0,0 +1,72 @@ +// 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 PropertyEnumValues: { + readonly Value1: 0; + readonly Value2: 1; +}; +export type PropertyEnumTag = typeof PropertyEnumValues[keyof typeof PropertyEnumValues]; + +export type PropertyEnumObject = typeof PropertyEnumValues & { + enumProperty: string; + readonly enumConstant: number; + computedEnum: string; +}; + +export {}; + +declare global { + namespace PropertyNamespace { + var namespaceConstant: string; + let namespaceProperty: string; + namespace Nested { + var nestedConstant: string; + let nestedDouble: number; + let nestedProperty: number; + } + } +} + +/// 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 PropertyClass extends SwiftHeapObject { +} +export type Exports = { + PropertyClass: { + new(): PropertyClass; + readonly staticConstant: string; + staticVariable: number; + jsObjectProperty: any; + classVariable: string; + computedProperty: string; + readonly readOnlyComputed: number; + optionalProperty: string | null; + } + PropertyEnum: PropertyEnumObject + PropertyNamespace: { + readonly namespaceConstant: string; + namespaceProperty: string; + Nested: { + readonly nestedConstant: string; + nestedDouble: number; + nestedProperty: number; + }, + }, +} +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/StaticProperties.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js new file mode 100644 index 000000000..05127cd14 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js @@ -0,0 +1,426 @@ +// 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 PropertyEnumValues = { + Value1: 0, + Value2: 1, +}; + +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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_PropertyClass_wrap"] = function(pointer) { + const obj = _exports['PropertyClass'].__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; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class PropertyClass extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_PropertyClass_deinit, PropertyClass.prototype); + } + + constructor() { + const ret = instance.exports.bjs_PropertyClass_init(); + return PropertyClass.__construct(ret); + } + static get staticConstant() { + instance.exports.bjs_PropertyClass_static_staticConstant_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + static get staticVariable() { + const ret = instance.exports.bjs_PropertyClass_static_staticVariable_get(); + return ret; + } + static set staticVariable(value) { + instance.exports.bjs_PropertyClass_static_staticVariable_set(value); + } + static get jsObjectProperty() { + const ret = instance.exports.bjs_PropertyClass_static_jsObjectProperty_get(); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + } + static set jsObjectProperty(value) { + instance.exports.bjs_PropertyClass_static_jsObjectProperty_set(swift.memory.retain(value)); + } + static get classVariable() { + instance.exports.bjs_PropertyClass_static_classVariable_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + static set classVariable(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyClass_static_classVariable_set(valueId, valueBytes.length); + } + static get computedProperty() { + instance.exports.bjs_PropertyClass_static_computedProperty_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + static set computedProperty(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyClass_static_computedProperty_set(valueId, valueBytes.length); + } + static get readOnlyComputed() { + const ret = instance.exports.bjs_PropertyClass_static_readOnlyComputed_get(); + return ret; + } + static get optionalProperty() { + instance.exports.bjs_PropertyClass_static_optionalProperty_get(); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + } + static set optionalProperty(value) { + const isSome = value != null; + let valueId, valueBytes; + if (isSome) { + valueBytes = textEncoder.encode(value); + valueId = swift.memory.retain(valueBytes); + } + instance.exports.bjs_PropertyClass_static_optionalProperty_set(+isSome, isSome ? valueId : 0, isSome ? valueBytes.length : 0); + } + } + if (typeof globalThis.PropertyNamespace === 'undefined') { + globalThis.PropertyNamespace = {}; + } + if (typeof globalThis.PropertyNamespace.Nested === 'undefined') { + globalThis.PropertyNamespace.Nested = {}; + } + const exports = { + PropertyClass, + PropertyEnum: { + ...PropertyEnumValues, + get enumProperty() { + instance.exports.bjs_PropertyEnum_static_enumProperty_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + set enumProperty(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyEnum_static_enumProperty_set(valueId, valueBytes.length); + }, + get enumConstant() { + const ret = instance.exports.bjs_PropertyEnum_static_enumConstant_get(); + return ret; + }, + get computedEnum() { + instance.exports.bjs_PropertyEnum_static_computedEnum_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + set computedEnum(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyEnum_static_computedEnum_set(valueId, valueBytes.length); + } + }, + PropertyNamespace: { + get namespaceProperty() { + instance.exports.bjs_PropertyNamespace_static_namespaceProperty_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + set namespaceProperty(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyNamespace_static_namespaceProperty_set(valueId, valueBytes.length); + }, + get namespaceConstant() { + instance.exports.bjs_PropertyNamespace_static_namespaceConstant_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + Nested: { + get nestedProperty() { + const ret = instance.exports.bjs_PropertyNamespace_Nested_static_nestedProperty_get(); + return ret; + }, + set nestedProperty(value) { + instance.exports.bjs_PropertyNamespace_Nested_static_nestedProperty_set(value); + }, + get nestedConstant() { + instance.exports.bjs_PropertyNamespace_Nested_static_nestedConstant_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + get nestedDouble() { + const ret = instance.exports.bjs_PropertyNamespace_Nested_static_nestedDouble_get(); + return ret; + }, + set nestedDouble(value) { + instance.exports.bjs_PropertyNamespace_Nested_static_nestedDouble_set(value); + }, + }, + }, + }; + _exports = exports; + Object.defineProperty(globalThis.PropertyNamespace, 'namespaceProperty', { + get: () => exports.PropertyNamespace.namespaceProperty, + set: (value) => { exports.PropertyNamespace.namespaceProperty = value; } + }); + Object.defineProperty(globalThis.PropertyNamespace, 'namespaceConstant', { + get: () => exports.PropertyNamespace.namespaceConstant, + }); + Object.defineProperty(globalThis.PropertyNamespace.Nested, 'nestedProperty', { + get: () => exports.PropertyNamespace.Nested.nestedProperty, + set: (value) => { exports.PropertyNamespace.Nested.nestedProperty = value; } + }); + Object.defineProperty(globalThis.PropertyNamespace.Nested, 'nestedConstant', { + get: () => exports.PropertyNamespace.Nested.nestedConstant, + }); + Object.defineProperty(globalThis.PropertyNamespace.Nested, 'nestedDouble', { + get: () => exports.PropertyNamespace.Nested.nestedDouble, + set: (value) => { exports.PropertyNamespace.Nested.nestedDouble = value; } + }); + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.d.ts new file mode 100644 index 000000000..4ce689edb --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.d.ts @@ -0,0 +1,58 @@ +// 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 PropertyEnumValues: { + readonly Value1: 0; + readonly Value2: 1; +}; +export type PropertyEnumTag = typeof PropertyEnumValues[keyof typeof PropertyEnumValues]; + +export type PropertyEnumObject = typeof PropertyEnumValues & { + enumProperty: string; + readonly enumConstant: number; + computedEnum: string; +}; + +/// 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 PropertyClass extends SwiftHeapObject { +} +export type Exports = { + PropertyClass: { + new(): PropertyClass; + readonly staticConstant: string; + staticVariable: number; + jsObjectProperty: any; + classVariable: string; + computedProperty: string; + readonly readOnlyComputed: number; + optionalProperty: string | null; + } + PropertyEnum: PropertyEnumObject + PropertyNamespace: { + readonly namespaceConstant: string; + namespaceProperty: string; + Nested: { + readonly nestedConstant: string; + nestedDouble: number; + nestedProperty: number; + }, + }, +} +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/StaticProperties.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js new file mode 100644 index 000000000..5e89f1bb4 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js @@ -0,0 +1,402 @@ +// 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 PropertyEnumValues = { + Value1: 0, + Value2: 1, +}; + +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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_PropertyClass_wrap"] = function(pointer) { + const obj = _exports['PropertyClass'].__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; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class PropertyClass extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_PropertyClass_deinit, PropertyClass.prototype); + } + + constructor() { + const ret = instance.exports.bjs_PropertyClass_init(); + return PropertyClass.__construct(ret); + } + static get staticConstant() { + instance.exports.bjs_PropertyClass_static_staticConstant_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + static get staticVariable() { + const ret = instance.exports.bjs_PropertyClass_static_staticVariable_get(); + return ret; + } + static set staticVariable(value) { + instance.exports.bjs_PropertyClass_static_staticVariable_set(value); + } + static get jsObjectProperty() { + const ret = instance.exports.bjs_PropertyClass_static_jsObjectProperty_get(); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + } + static set jsObjectProperty(value) { + instance.exports.bjs_PropertyClass_static_jsObjectProperty_set(swift.memory.retain(value)); + } + static get classVariable() { + instance.exports.bjs_PropertyClass_static_classVariable_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + static set classVariable(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyClass_static_classVariable_set(valueId, valueBytes.length); + } + static get computedProperty() { + instance.exports.bjs_PropertyClass_static_computedProperty_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + static set computedProperty(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyClass_static_computedProperty_set(valueId, valueBytes.length); + } + static get readOnlyComputed() { + const ret = instance.exports.bjs_PropertyClass_static_readOnlyComputed_get(); + return ret; + } + static get optionalProperty() { + instance.exports.bjs_PropertyClass_static_optionalProperty_get(); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + } + static set optionalProperty(value) { + const isSome = value != null; + let valueId, valueBytes; + if (isSome) { + valueBytes = textEncoder.encode(value); + valueId = swift.memory.retain(valueBytes); + } + instance.exports.bjs_PropertyClass_static_optionalProperty_set(+isSome, isSome ? valueId : 0, isSome ? valueBytes.length : 0); + } + } + const exports = { + PropertyClass, + PropertyEnum: { + ...PropertyEnumValues, + get enumProperty() { + instance.exports.bjs_PropertyEnum_static_enumProperty_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + set enumProperty(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyEnum_static_enumProperty_set(valueId, valueBytes.length); + }, + get enumConstant() { + const ret = instance.exports.bjs_PropertyEnum_static_enumConstant_get(); + return ret; + }, + get computedEnum() { + instance.exports.bjs_PropertyEnum_static_computedEnum_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + set computedEnum(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyEnum_static_computedEnum_set(valueId, valueBytes.length); + } + }, + PropertyNamespace: { + get namespaceProperty() { + instance.exports.bjs_PropertyNamespace_static_namespaceProperty_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + set namespaceProperty(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyNamespace_static_namespaceProperty_set(valueId, valueBytes.length); + }, + get namespaceConstant() { + instance.exports.bjs_PropertyNamespace_static_namespaceConstant_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + Nested: { + get nestedProperty() { + const ret = instance.exports.bjs_PropertyNamespace_Nested_static_nestedProperty_get(); + return ret; + }, + set nestedProperty(value) { + instance.exports.bjs_PropertyNamespace_Nested_static_nestedProperty_set(value); + }, + get nestedConstant() { + instance.exports.bjs_PropertyNamespace_Nested_static_nestedConstant_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + get nestedDouble() { + const ret = instance.exports.bjs_PropertyNamespace_Nested_static_nestedDouble_get(); + return ret; + }, + set nestedDouble(value) { + instance.exports.bjs_PropertyNamespace_Nested_static_nestedDouble_set(value); + }, + }, + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.js deleted file mode 100644 index ea47fb555..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.js +++ /dev/null @@ -1,76 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - - }, - 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; - - return { - checkString: function bjs_checkString(a) { - const aBytes = textEncoder.encode(a); - const aId = swift.memory.retain(aBytes); - instance.exports.bjs_checkString(aId, aBytes.length); - swift.memory.release(aId); - }, - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.js deleted file mode 100644 index 16ed1081e..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.js +++ /dev/null @@ -1,89 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_checkString"] = function bjs_checkString(a) { - try { - const aObject = swift.memory.getObject(a); - swift.memory.release(a); - imports.checkString(aObject); - } catch (error) { - setException(error); - } - } - TestModule["bjs_checkStringWithLength"] = function bjs_checkStringWithLength(a, b) { - try { - const aObject = swift.memory.getObject(a); - swift.memory.release(a); - imports.checkStringWithLength(aObject, b); - } 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; - - return { - - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.d.ts similarity index 89% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.d.ts rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.d.ts index 09fd7b638..5e45162a1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.d.ts @@ -5,6 +5,8 @@ // `swift package bridge-js`. export type Exports = { + checkString(a: string): void; + roundtripString(a: string): string; } export type Imports = { checkString(a: string): void; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js new file mode 100644 index 000000000..0f92074d4 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js @@ -0,0 +1,249 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_checkString"] = function bjs_checkString(a) { + try { + const aObject = swift.memory.getObject(a); + swift.memory.release(a); + imports.checkString(aObject); + } catch (error) { + setException(error); + } + } + TestModule["bjs_checkStringWithLength"] = function bjs_checkStringWithLength(a, b) { + try { + const aObject = swift.memory.getObject(a); + swift.memory.release(a); + imports.checkStringWithLength(aObject, b); + } 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 = { + checkString: function bjs_checkString(a) { + const aBytes = textEncoder.encode(a); + const aId = swift.memory.retain(aBytes); + instance.exports.bjs_checkString(aId, aBytes.length); + }, + roundtripString: function bjs_roundtripString(a) { + const aBytes = textEncoder.encode(a); + const aId = swift.memory.retain(aBytes); + instance.exports.bjs_roundtripString(aId, aBytes.length); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.js deleted file mode 100644 index f98cea559..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.js +++ /dev/null @@ -1,76 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - - }, - 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; - - return { - checkString: function bjs_checkString() { - instance.exports.bjs_checkString(); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - }, - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.d.ts deleted file mode 100644 index cb7783667..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -// 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 type Exports = { -} -export type Imports = { - checkString(): string; -} -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/StringReturn.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.js deleted file mode 100644 index 3220ae7b0..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.js +++ /dev/null @@ -1,80 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_checkString"] = function bjs_checkString() { - try { - let ret = imports.checkString(); - tmpRetBytes = textEncoder.encode(ret); - return tmpRetBytes.length; - } 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; - - return { - - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.d.ts similarity index 95% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.d.ts rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.d.ts index c6a9f65a4..b43ff062c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.d.ts @@ -8,6 +8,7 @@ export type Exports = { checkString(): string; } export type Imports = { + checkString(): string; } export function createInstantiator(options: { imports: Imports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js new file mode 100644 index 000000000..f86fce218 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js @@ -0,0 +1,233 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_checkString"] = function bjs_checkString() { + try { + let ret = imports.checkString(); + tmpRetBytes = textEncoder.encode(ret); + return tmpRetBytes.length; + } 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 = { + checkString: function bjs_checkString() { + instance.exports.bjs_checkString(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.js deleted file mode 100644 index ab4caba34..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.js +++ /dev/null @@ -1,125 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - // Wrapper functions for module: TestModule - if (!importObject["TestModule"]) { - importObject["TestModule"] = {}; - } - importObject["TestModule"]["bjs_Greeter_wrap"] = function(pointer) { - const obj = Greeter.__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 Greeter extends SwiftHeapObject { - static __construct(ptr) { - return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Greeter_deinit, Greeter.prototype); - } - - - constructor(name) { - const nameBytes = textEncoder.encode(name); - const nameId = swift.memory.retain(nameBytes); - const ret = instance.exports.bjs_Greeter_init(nameId, nameBytes.length); - swift.memory.release(nameId); - return Greeter.__construct(ret); - } - greet() { - instance.exports.bjs_Greeter_greet(this.pointer); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - } - changeName(name) { - const nameBytes = textEncoder.encode(name); - const nameId = swift.memory.retain(nameBytes); - instance.exports.bjs_Greeter_changeName(this.pointer, nameId, nameBytes.length); - swift.memory.release(nameId); - } - } - return { - Greeter, - takeGreeter: function bjs_takeGreeter(greeter) { - instance.exports.bjs_takeGreeter(greeter.pointer); - }, - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.d.ts new file mode 100644 index 000000000..05fc97fee --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.d.ts @@ -0,0 +1,43 @@ +// 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`. + +/// 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 Greeter extends SwiftHeapObject { + greet(): string; + changeName(name: string): void; + name: string; +} +export interface PublicGreeter extends SwiftHeapObject { +} +export interface PackageGreeter extends SwiftHeapObject { +} +export type Exports = { + Greeter: { + new(name: string): Greeter; + } + PublicGreeter: { + } + PackageGreeter: { + } + takeGreeter(greeter: Greeter): void; +} +export type Imports = { + jsRoundTripGreeter(greeter: Greeter): Greeter; + jsRoundTripOptionalGreeter(greeter: Greeter | null): Greeter | null; +} +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/SwiftClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js new file mode 100644 index 000000000..8f0552b64 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js @@ -0,0 +1,333 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_Greeter_wrap"] = function(pointer) { + const obj = _exports['Greeter'].__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_PackageGreeter_wrap"] = function(pointer) { + const obj = _exports['PackageGreeter'].__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_PublicGreeter_wrap"] = function(pointer) { + const obj = _exports['PublicGreeter'].__construct(pointer); + return swift.memory.retain(obj); + }; + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_jsRoundTripGreeter"] = function bjs_jsRoundTripGreeter(greeter) { + try { + let ret = imports.jsRoundTripGreeter(_exports['Greeter'].__construct(greeter)); + return ret.pointer; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_jsRoundTripOptionalGreeter"] = function bjs_jsRoundTripOptionalGreeter(greeterIsSome, greeterWrappedValue) { + try { + let ret = imports.jsRoundTripOptionalGreeter(greeterIsSome ? _exports['Greeter'].__construct(greeterWrappedValue) : null); + const isSome = ret != null; + return isSome ? ret.pointer : 0; + } 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 swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class Greeter extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Greeter_deinit, Greeter.prototype); + } + + constructor(name) { + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + const ret = instance.exports.bjs_Greeter_init(nameId, nameBytes.length); + return Greeter.__construct(ret); + } + greet() { + instance.exports.bjs_Greeter_greet(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + changeName(name) { + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + instance.exports.bjs_Greeter_changeName(this.pointer, nameId, nameBytes.length); + } + get name() { + instance.exports.bjs_Greeter_name_get(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + set name(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_Greeter_name_set(this.pointer, valueId, valueBytes.length); + } + } + class PublicGreeter extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_PublicGreeter_deinit, PublicGreeter.prototype); + } + + } + class PackageGreeter extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_PackageGreeter_deinit, PackageGreeter.prototype); + } + + } + const exports = { + Greeter, + PublicGreeter, + PackageGreeter, + takeGreeter: function bjs_takeGreeter(greeter) { + instance.exports.bjs_takeGreeter(greeter.pointer); + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.d.ts new file mode 100644 index 000000000..ccc95eb3b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.d.ts @@ -0,0 +1,104 @@ +// 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 ThemeValues: { + readonly Light: "light"; + readonly Dark: "dark"; + readonly Auto: "auto"; +}; +export type ThemeTag = typeof ThemeValues[keyof typeof ThemeValues]; + +export const HttpStatusValues: { + readonly Ok: 200; + readonly NotFound: 404; + readonly ServerError: 500; + readonly Unknown: -1; +}; +export type HttpStatusTag = typeof HttpStatusValues[keyof typeof HttpStatusValues]; + +export const APIResultValues: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + readonly Flag: 2; + readonly Rate: 3; + readonly Precise: 4; + readonly Info: 5; + }; +}; + +export type APIResultTag = + { tag: typeof APIResultValues.Tag.Success; param0: string } | { tag: typeof APIResultValues.Tag.Failure; param0: number } | { tag: typeof APIResultValues.Tag.Flag; param0: boolean } | { tag: typeof APIResultValues.Tag.Rate; param0: number } | { tag: typeof APIResultValues.Tag.Precise; param0: number } | { tag: typeof APIResultValues.Tag.Info } + +export type DirectionObject = typeof DirectionValues; + +export type ThemeObject = typeof ThemeValues; + +export type HttpStatusObject = typeof HttpStatusValues; + +export type APIResultObject = typeof APIResultValues; + +/// 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 Person extends SwiftHeapObject { +} +export interface TestProcessor extends SwiftHeapObject { +} +export type Exports = { + Person: { + new(name: string): Person; + } + TestProcessor: { + new(transform: (arg0: string) => string): TestProcessor; + } + roundtripString(stringClosure: (arg0: string) => string): (arg0: string) => string; + roundtripInt(intClosure: (arg0: number) => number): (arg0: number) => number; + roundtripBool(boolClosure: (arg0: boolean) => boolean): (arg0: boolean) => boolean; + roundtripFloat(floatClosure: (arg0: number) => number): (arg0: number) => number; + roundtripDouble(doubleClosure: (arg0: number) => number): (arg0: number) => number; + roundtripOptionalString(stringClosure: (arg0: string | null) => string | null): (arg0: string | null) => string | null; + roundtripOptionalInt(intClosure: (arg0: number | null) => number | null): (arg0: number | null) => number | null; + roundtripOptionalBool(boolClosure: (arg0: boolean | null) => boolean | null): (arg0: boolean | null) => boolean | null; + roundtripOptionalFloat(floatClosure: (arg0: number | null) => number | null): (arg0: number | null) => number | null; + roundtripOptionalDouble(doubleClosure: (arg0: number | null) => number | null): (arg0: number | null) => number | null; + roundtripPerson(personClosure: (arg0: Person) => Person): (arg0: Person) => Person; + roundtripOptionalPerson(personClosure: (arg0: Person | null) => Person | null): (arg0: Person | null) => Person | null; + roundtripDirection(callback: (arg0: DirectionTag) => DirectionTag): (arg0: DirectionTag) => DirectionTag; + roundtripTheme(callback: (arg0: ThemeTag) => ThemeTag): (arg0: ThemeTag) => ThemeTag; + roundtripHttpStatus(callback: (arg0: HttpStatusTag) => HttpStatusTag): (arg0: HttpStatusTag) => HttpStatusTag; + roundtripAPIResult(callback: (arg0: APIResultTag) => APIResultTag): (arg0: APIResultTag) => APIResultTag; + roundtripOptionalDirection(callback: (arg0: DirectionTag | null) => DirectionTag | null): (arg0: DirectionTag | null) => DirectionTag | null; + roundtripOptionalTheme(callback: (arg0: ThemeTag | null) => ThemeTag | null): (arg0: ThemeTag | null) => ThemeTag | null; + roundtripOptionalHttpStatus(callback: (arg0: HttpStatusTag | null) => HttpStatusTag | null): (arg0: HttpStatusTag | null) => HttpStatusTag | null; + roundtripOptionalAPIResult(callback: (arg0: APIResultTag | null) => APIResultTag | null): (arg0: APIResultTag | null) => APIResultTag | null; + roundtripOptionalDirection(callback: (arg0: DirectionTag | null) => DirectionTag | null): (arg0: DirectionTag | null) => DirectionTag | null; + Direction: DirectionObject + Theme: ThemeObject + HttpStatus: HttpStatusObject + APIResult: APIResultObject +} +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/SwiftClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js new file mode 100644 index 000000000..5fbde8c82 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js @@ -0,0 +1,1079 @@ +// 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 ThemeValues = { + Light: "light", + Dark: "dark", + Auto: "auto", +}; + +export const HttpStatusValues = { + Ok: 200, + NotFound: 404, + ServerError: 500, + Unknown: -1, +}; + +export const APIResultValues = { + Tag: { + Success: 0, + Failure: 1, + Flag: 2, + Rate: 3, + Precise: 4, + Info: 5, + }, +}; +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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const swiftClosureRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.unregistered) { return; } + instance?.exports?.bjs_release_swift_closure(state.pointer); + }); + const makeClosure = (pointer, file, line, func) => { + const state = { pointer, file, line, unregistered: false }; + const real = (...args) => { + if (state.unregistered) { + const bytes = new Uint8Array(memory.buffer, state.file); + let length = 0; + while (bytes[length] !== 0) { length += 1; } + const fileID = textDecoder.decode(bytes.subarray(0, length)); + throw new Error(`Attempted to call a released JSTypedClosure created at ${fileID}:${state.line}`); + } + return func(...args); + }; + real.__unregister = () => { + if (state.unregistered) { return; } + state.unregistered = true; + swiftClosureRegistry.unregister(state); + }; + swiftClosureRegistry.register(real, state, state); + return swift.memory.retain(real); + }; + + const __bjs_createAPIResultValuesHelpers = () => { + return () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case APIResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Success, cleanup }; + } + case APIResultValues.Tag.Failure: { + i32Stack.push((value.param0 | 0)); + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Failure, cleanup }; + } + case APIResultValues.Tag.Flag: { + i32Stack.push(value.param0 ? 1 : 0); + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Flag, cleanup }; + } + case APIResultValues.Tag.Rate: { + f32Stack.push(Math.fround(value.param0)); + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Rate, cleanup }; + } + case APIResultValues.Tag.Precise: { + f64Stack.push(value.param0); + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Precise, cleanup }; + } + case APIResultValues.Tag.Info: { + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Info, cleanup }; + } + default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case APIResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: APIResultValues.Tag.Success, param0: string }; + } + case APIResultValues.Tag.Failure: { + const int = i32Stack.pop(); + return { tag: APIResultValues.Tag.Failure, param0: int }; + } + case APIResultValues.Tag.Flag: { + const bool = i32Stack.pop() !== 0; + return { tag: APIResultValues.Tag.Flag, param0: bool }; + } + case APIResultValues.Tag.Rate: { + const f32 = f32Stack.pop(); + return { tag: APIResultValues.Tag.Rate, param0: f32 }; + } + case APIResultValues.Tag.Precise: { + const f64 = f64Stack.pop(); + return { tag: APIResultValues.Tag.Precise, param0: f64 }; + } + case APIResultValues.Tag.Info: return { tag: APIResultValues.Tag.Info }; + default: throw new Error("Unknown APIResultValues tag returned from Swift: " + String(tag)); + } + } + }); + }; + + return { + /** + * @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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + bjs["swift_js_closure_unregister"] = function(funcRef) { + const func = swift.memory.getObject(funcRef); + func.__unregister(); + } + bjs["invoke_js_callback_TestModule_10TestModule10HttpStatusO_10HttpStatusO"] = function(callbackId, param0) { + try { + const callback = swift.memory.getObject(callbackId); + let ret = callback(param0); + return ret; + } catch (error) { + setException(error); + return 0 + } + } + bjs["make_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO = function(param0) { + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO(boxPtr, param0); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return ret; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO); + } + bjs["invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO"] = function(callbackId, param0) { + try { + const callback = swift.memory.getObject(callbackId); + const param0Object = swift.memory.getObject(param0); + swift.memory.release(param0); + let ret = callback(param0Object); + tmpRetBytes = textEncoder.encode(ret); + return tmpRetBytes.length; + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule5ThemeO_5ThemeO = function(param0) { + const param0Bytes = textEncoder.encode(param0); + const param0Id = swift.memory.retain(param0Bytes); + instance.exports.invoke_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO(boxPtr, param0Id, param0Bytes.length); + const ret = tmpRetString; + tmpRetString = undefined; + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return ret; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule5ThemeO_5ThemeO); + } + bjs["invoke_js_callback_TestModule_10TestModule6PersonC_6PersonC"] = function(callbackId, param0) { + try { + const callback = swift.memory.getObject(callbackId); + let ret = callback(_exports['Person'].__construct(param0)); + return ret.pointer; + } catch (error) { + setException(error); + return 0 + } + } + bjs["make_swift_closure_TestModule_10TestModule6PersonC_6PersonC"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule6PersonC_6PersonC = function(param0) { + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModule6PersonC_6PersonC(boxPtr, param0.pointer); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return _exports['Person'].__construct(ret); + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule6PersonC_6PersonC); + } + bjs["invoke_js_callback_TestModule_10TestModule9APIResultO_9APIResultO"] = function(callbackId, param0) { + try { + const callback = swift.memory.getObject(callbackId); + const enumValue = enumHelpers.APIResult.lift(param0); + let ret = callback(enumValue); + const { caseId: caseId, cleanup: cleanup } = enumHelpers.APIResult.lower(ret); + return caseId; + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule9APIResultO_9APIResultO = function(param0) { + const { caseId: param0CaseId, cleanup: param0Cleanup } = enumHelpers.APIResult.lower(param0); + instance.exports.invoke_swift_closure_TestModule_10TestModule9APIResultO_9APIResultO(boxPtr, param0CaseId); + const ret = enumHelpers.APIResult.lift(i32Stack.pop()); + if (param0Cleanup) { param0Cleanup(); } + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return ret; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule9APIResultO_9APIResultO); + } + bjs["invoke_js_callback_TestModule_10TestModule9DirectionO_9DirectionO"] = function(callbackId, param0) { + try { + const callback = swift.memory.getObject(callbackId); + let ret = callback(param0); + return ret; + } catch (error) { + setException(error); + return 0 + } + } + bjs["make_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule9DirectionO_9DirectionO = function(param0) { + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO(boxPtr, param0); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return ret; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule9DirectionO_9DirectionO); + } + bjs["invoke_js_callback_TestModule_10TestModuleSS_SS"] = function(callbackId, param0) { + try { + const callback = swift.memory.getObject(callbackId); + const param0Object = swift.memory.getObject(param0); + swift.memory.release(param0); + let ret = callback(param0Object); + tmpRetBytes = textEncoder.encode(ret); + return tmpRetBytes.length; + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModuleSS_SS"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSS_SS = function(param0) { + const param0Bytes = textEncoder.encode(param0); + const param0Id = swift.memory.retain(param0Bytes); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSS_SS(boxPtr, param0Id, param0Bytes.length); + const ret = tmpRetString; + tmpRetString = undefined; + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return ret; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSS_SS); + } + bjs["invoke_js_callback_TestModule_10TestModuleSb_Sb"] = function(callbackId, param0) { + try { + const callback = swift.memory.getObject(callbackId); + let ret = callback(param0 !== 0); + return ret ? 1 : 0; + } catch (error) { + setException(error); + return 0 + } + } + bjs["make_swift_closure_TestModule_10TestModuleSb_Sb"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSb_Sb = function(param0) { + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModuleSb_Sb(boxPtr, param0); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return ret !== 0; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSb_Sb); + } + bjs["invoke_js_callback_TestModule_10TestModuleSd_Sd"] = function(callbackId, param0) { + try { + const callback = swift.memory.getObject(callbackId); + let ret = callback(param0); + return ret; + } catch (error) { + setException(error); + return 0 + } + } + bjs["make_swift_closure_TestModule_10TestModuleSd_Sd"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSd_Sd = function(param0) { + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModuleSd_Sd(boxPtr, param0); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return ret; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSd_Sd); + } + bjs["invoke_js_callback_TestModule_10TestModuleSf_Sf"] = function(callbackId, param0) { + try { + const callback = swift.memory.getObject(callbackId); + let ret = callback(param0); + return ret; + } catch (error) { + setException(error); + return 0 + } + } + bjs["make_swift_closure_TestModule_10TestModuleSf_Sf"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSf_Sf = function(param0) { + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModuleSf_Sf(boxPtr, param0); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return ret; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSf_Sf); + } + bjs["invoke_js_callback_TestModule_10TestModuleSi_Si"] = function(callbackId, param0) { + try { + const callback = swift.memory.getObject(callbackId); + let ret = callback(param0); + return ret; + } catch (error) { + setException(error); + return 0 + } + } + bjs["make_swift_closure_TestModule_10TestModuleSi_Si"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSi_Si = function(param0) { + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModuleSi_Si(boxPtr, param0); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return ret; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSi_Si); + } + bjs["invoke_js_callback_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO"] = function(callbackId, param0IsSome, param0WrappedValue) { + try { + const callback = swift.memory.getObject(callbackId); + let ret = callback(param0IsSome ? param0WrappedValue : null); + const isSome = ret != null; + bjs["swift_js_return_optional_int"](isSome ? 1 : 0, isSome ? (ret | 0) : 0); + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO = function(param0) { + const isSome = param0 != null; + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return optResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO); + } + bjs["invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO"] = function(callbackId, param0IsSome, param0WrappedValue) { + try { + const callback = swift.memory.getObject(callbackId); + let obj; + if (param0IsSome) { + obj = swift.memory.getObject(param0WrappedValue); + swift.memory.release(param0WrappedValue); + } + let ret = callback(param0IsSome ? obj : null); + const isSome = ret != null; + if (isSome) { + tmpRetString = ret; + } else { + tmpRetString = null; + } + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO = function(param0) { + const isSome = param0 != null; + let param0Id, param0Bytes; + if (isSome) { + param0Bytes = textEncoder.encode(param0); + param0Id = swift.memory.retain(param0Bytes); + } + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(boxPtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return optResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO); + } + bjs["invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC"] = function(callbackId, param0IsSome, param0WrappedValue) { + try { + const callback = swift.memory.getObject(callbackId); + let ret = callback(param0IsSome ? _exports['Person'].__construct(param0WrappedValue) : null); + const isSome = ret != null; + return isSome ? ret.pointer : 0; + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC = function(param0) { + const isSome = param0 != null; + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC(boxPtr, +isSome, isSome ? param0.pointer : 0); + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + const optResult = pointer === null ? null : _exports['Person'].__construct(pointer); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return optResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq6PersonC_Sq6PersonC); + } + bjs["invoke_js_callback_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO"] = function(callbackId, param0IsSome, param0WrappedValue) { + try { + const callback = swift.memory.getObject(callbackId); + let enumValue; + if (param0IsSome) { + enumValue = enumHelpers.APIResult.lift(param0WrappedValue); + } + let ret = callback(param0IsSome ? enumValue : null); + const isSome = ret != null; + if (isSome) { + const { caseId: caseId, cleanup: cleanup } = enumHelpers.APIResult.lower(ret); + return caseId; + } else { + return -1; + } + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO = function(param0) { + const isSome = param0 != null; + let param0CaseId, param0Cleanup; + if (isSome) { + const enumResult = enumHelpers.APIResult.lower(param0); + param0CaseId = enumResult.caseId; + param0Cleanup = enumResult.cleanup; + } + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO(boxPtr, +isSome, isSome ? param0CaseId : 0); + const tag = i32Stack.pop(); + const isNull = (tag === -1); + let optResult; + if (isNull) { + optResult = null; + } else { + optResult = enumHelpers.APIResult.lift(tag); + } + if (param0Cleanup) { param0Cleanup(); } + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return optResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq9APIResultO_Sq9APIResultO); + } + bjs["invoke_js_callback_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO"] = function(callbackId, param0IsSome, param0WrappedValue) { + try { + const callback = swift.memory.getObject(callbackId); + let ret = callback(param0IsSome ? param0WrappedValue : null); + const isSome = ret != null; + return isSome ? (ret | 0) : -1; + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO = function(param0) { + const isSome = param0 != null; + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return optResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO); + } + bjs["invoke_js_callback_TestModule_10TestModuleSqSS_SqSS"] = function(callbackId, param0IsSome, param0WrappedValue) { + try { + const callback = swift.memory.getObject(callbackId); + let obj; + if (param0IsSome) { + obj = swift.memory.getObject(param0WrappedValue); + swift.memory.release(param0WrappedValue); + } + let ret = callback(param0IsSome ? obj : null); + const isSome = ret != null; + if (isSome) { + tmpRetString = ret; + } else { + tmpRetString = null; + } + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModuleSqSS_SqSS"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSqSS_SqSS = function(param0) { + const isSome = param0 != null; + let param0Id, param0Bytes; + if (isSome) { + param0Bytes = textEncoder.encode(param0); + param0Id = swift.memory.retain(param0Bytes); + } + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSS_SqSS(boxPtr, +isSome, isSome ? param0Id : 0, isSome ? param0Bytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return optResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSS_SqSS); + } + bjs["invoke_js_callback_TestModule_10TestModuleSqSb_SqSb"] = function(callbackId, param0IsSome, param0WrappedValue) { + try { + const callback = swift.memory.getObject(callbackId); + let ret = callback(param0IsSome ? param0WrappedValue !== 0 : null); + const isSome = ret != null; + bjs["swift_js_return_optional_bool"](isSome ? 1 : 0, isSome ? (ret ? 1 : 0) : 0); + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModuleSqSb_SqSb"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSqSb_SqSb = function(param0) { + const isSome = param0 != null; + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSb_SqSb(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalBool; + tmpRetOptionalBool = undefined; + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return optResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSb_SqSb); + } + bjs["invoke_js_callback_TestModule_10TestModuleSqSd_SqSd"] = function(callbackId, param0IsSome, param0WrappedValue) { + try { + const callback = swift.memory.getObject(callbackId); + let ret = callback(param0IsSome ? param0WrappedValue : null); + const isSome = ret != null; + bjs["swift_js_return_optional_double"](isSome ? 1 : 0, isSome ? ret : 0.0); + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModuleSqSd_SqSd"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSqSd_SqSd = function(param0) { + const isSome = param0 != null; + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSd_SqSd(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return optResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSd_SqSd); + } + bjs["invoke_js_callback_TestModule_10TestModuleSqSf_SqSf"] = function(callbackId, param0IsSome, param0WrappedValue) { + try { + const callback = swift.memory.getObject(callbackId); + let ret = callback(param0IsSome ? param0WrappedValue : null); + const isSome = ret != null; + bjs["swift_js_return_optional_float"](isSome ? 1 : 0, isSome ? Math.fround(ret) : 0.0); + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModuleSqSf_SqSf"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSqSf_SqSf = function(param0) { + const isSome = param0 != null; + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSf_SqSf(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return optResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSf_SqSf); + } + bjs["invoke_js_callback_TestModule_10TestModuleSqSi_SqSi"] = function(callbackId, param0IsSome, param0WrappedValue) { + try { + const callback = swift.memory.getObject(callbackId); + let ret = callback(param0IsSome ? param0WrappedValue : null); + const isSome = ret != null; + bjs["swift_js_return_optional_int"](isSome ? 1 : 0, isSome ? (ret | 0) : 0); + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModuleSqSi_SqSi"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSqSi_SqSi = function(param0) { + const isSome = param0 != null; + instance.exports.invoke_swift_closure_TestModule_10TestModuleSqSi_SqSi(boxPtr, +isSome, isSome ? param0 : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return optResult; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSi_SqSi); + } + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_Person_wrap"] = function(pointer) { + const obj = _exports['Person'].__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_TestProcessor_wrap"] = function(pointer) { + const obj = _exports['TestProcessor'].__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; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class Person extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Person_deinit, Person.prototype); + } + + constructor(name) { + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + const ret = instance.exports.bjs_Person_init(nameId, nameBytes.length); + return Person.__construct(ret); + } + } + class TestProcessor extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_TestProcessor_deinit, TestProcessor.prototype); + } + + constructor(transform) { + const callbackId = swift.memory.retain(transform); + const ret = instance.exports.bjs_TestProcessor_init(callbackId); + return TestProcessor.__construct(ret); + } + } + const APIResultHelpers = __bjs_createAPIResultValuesHelpers()(); + enumHelpers.APIResult = APIResultHelpers; + + const exports = { + Person, + TestProcessor, + roundtripString: function bjs_roundtripString(stringClosure) { + const callbackId = swift.memory.retain(stringClosure); + const ret = instance.exports.bjs_roundtripString(callbackId); + return swift.memory.getObject(ret); + }, + roundtripInt: function bjs_roundtripInt(intClosure) { + const callbackId = swift.memory.retain(intClosure); + const ret = instance.exports.bjs_roundtripInt(callbackId); + return swift.memory.getObject(ret); + }, + roundtripBool: function bjs_roundtripBool(boolClosure) { + const callbackId = swift.memory.retain(boolClosure); + const ret = instance.exports.bjs_roundtripBool(callbackId); + return swift.memory.getObject(ret); + }, + roundtripFloat: function bjs_roundtripFloat(floatClosure) { + const callbackId = swift.memory.retain(floatClosure); + const ret = instance.exports.bjs_roundtripFloat(callbackId); + return swift.memory.getObject(ret); + }, + roundtripDouble: function bjs_roundtripDouble(doubleClosure) { + const callbackId = swift.memory.retain(doubleClosure); + const ret = instance.exports.bjs_roundtripDouble(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalString: function bjs_roundtripOptionalString(stringClosure) { + const callbackId = swift.memory.retain(stringClosure); + const ret = instance.exports.bjs_roundtripOptionalString(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalInt: function bjs_roundtripOptionalInt(intClosure) { + const callbackId = swift.memory.retain(intClosure); + const ret = instance.exports.bjs_roundtripOptionalInt(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalBool: function bjs_roundtripOptionalBool(boolClosure) { + const callbackId = swift.memory.retain(boolClosure); + const ret = instance.exports.bjs_roundtripOptionalBool(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalFloat: function bjs_roundtripOptionalFloat(floatClosure) { + const callbackId = swift.memory.retain(floatClosure); + const ret = instance.exports.bjs_roundtripOptionalFloat(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalDouble: function bjs_roundtripOptionalDouble(doubleClosure) { + const callbackId = swift.memory.retain(doubleClosure); + const ret = instance.exports.bjs_roundtripOptionalDouble(callbackId); + return swift.memory.getObject(ret); + }, + roundtripPerson: function bjs_roundtripPerson(personClosure) { + const callbackId = swift.memory.retain(personClosure); + const ret = instance.exports.bjs_roundtripPerson(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalPerson: function bjs_roundtripOptionalPerson(personClosure) { + const callbackId = swift.memory.retain(personClosure); + const ret = instance.exports.bjs_roundtripOptionalPerson(callbackId); + return swift.memory.getObject(ret); + }, + roundtripDirection: function bjs_roundtripDirection(callback) { + const callbackId = swift.memory.retain(callback); + const ret = instance.exports.bjs_roundtripDirection(callbackId); + return swift.memory.getObject(ret); + }, + roundtripTheme: function bjs_roundtripTheme(callback) { + const callbackId = swift.memory.retain(callback); + const ret = instance.exports.bjs_roundtripTheme(callbackId); + return swift.memory.getObject(ret); + }, + roundtripHttpStatus: function bjs_roundtripHttpStatus(callback) { + const callbackId = swift.memory.retain(callback); + const ret = instance.exports.bjs_roundtripHttpStatus(callbackId); + return swift.memory.getObject(ret); + }, + roundtripAPIResult: function bjs_roundtripAPIResult(callback) { + const callbackId = swift.memory.retain(callback); + const ret = instance.exports.bjs_roundtripAPIResult(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalDirection: function bjs_roundtripOptionalDirection(callback) { + const callbackId = swift.memory.retain(callback); + const ret = instance.exports.bjs_roundtripOptionalDirection(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalTheme: function bjs_roundtripOptionalTheme(callback) { + const callbackId = swift.memory.retain(callback); + const ret = instance.exports.bjs_roundtripOptionalTheme(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalHttpStatus: function bjs_roundtripOptionalHttpStatus(callback) { + const callbackId = swift.memory.retain(callback); + const ret = instance.exports.bjs_roundtripOptionalHttpStatus(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalAPIResult: function bjs_roundtripOptionalAPIResult(callback) { + const callbackId = swift.memory.retain(callback); + const ret = instance.exports.bjs_roundtripOptionalAPIResult(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalDirection: function bjs_roundtripOptionalDirection(callback) { + const callbackId = swift.memory.retain(callback); + const ret = instance.exports.bjs_roundtripOptionalDirection(callbackId); + return swift.memory.getObject(ret); + }, + Direction: DirectionValues, + Theme: ThemeValues, + HttpStatus: HttpStatusValues, + APIResult: APIResultValues, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.d.ts new file mode 100644 index 000000000..ebf493910 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.d.ts @@ -0,0 +1,19 @@ +// 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 type Exports = { +} +export type Imports = { + applyInt(value: number, transform: (arg0: number) => number): number; + makeAdder(base: number): (arg0: number) => number; +} +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/SwiftClosureImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js new file mode 100644 index 000000000..61347e817 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js @@ -0,0 +1,291 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const swiftClosureRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.unregistered) { return; } + instance?.exports?.bjs_release_swift_closure(state.pointer); + }); + const makeClosure = (pointer, file, line, func) => { + const state = { pointer, file, line, unregistered: false }; + const real = (...args) => { + if (state.unregistered) { + const bytes = new Uint8Array(memory.buffer, state.file); + let length = 0; + while (bytes[length] !== 0) { length += 1; } + const fileID = textDecoder.decode(bytes.subarray(0, length)); + throw new Error(`Attempted to call a released JSTypedClosure created at ${fileID}:${state.line}`); + } + return func(...args); + }; + real.__unregister = () => { + if (state.unregistered) { return; } + state.unregistered = true; + swiftClosureRegistry.unregister(state); + }; + swiftClosureRegistry.register(real, state, state); + return swift.memory.retain(real); + }; + + + return { + /** + * @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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + bjs["swift_js_closure_unregister"] = function(funcRef) { + const func = swift.memory.getObject(funcRef); + func.__unregister(); + } + bjs["invoke_js_callback_TestModule_10TestModuleSi_Si"] = function(callbackId, param0) { + try { + const callback = swift.memory.getObject(callbackId); + let ret = callback(param0); + return ret; + } catch (error) { + setException(error); + return 0 + } + } + bjs["make_swift_closure_TestModule_10TestModuleSi_Si"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSi_Si = function(param0) { + const ret = instance.exports.invoke_swift_closure_TestModule_10TestModuleSi_Si(boxPtr, param0); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return ret; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSi_Si); + } + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_applyInt"] = function bjs_applyInt(value, transform) { + try { + let ret = imports.applyInt(value, swift.memory.getObject(transform)); + return ret; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_makeAdder"] = function bjs_makeAdder(base) { + try { + let ret = imports.makeAdder(base); + if (typeof ret !== "function") { + throw new TypeError("Expected a function") + } + return swift.memory.retain(ret); + } catch (error) { + setException(error); + return 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 exports = { + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.d.ts new file mode 100644 index 000000000..4a61a26e3 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.d.ts @@ -0,0 +1,85 @@ +// 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 PrecisionValues: { + readonly Rough: 0.1; + readonly Fine: 0.001; +}; +export type PrecisionTag = typeof PrecisionValues[keyof typeof PrecisionValues]; + +export interface DataPoint { + x: number; + y: number; + label: string; + optCount: number | null; + optFlag: boolean | null; +} +export interface Address { + street: string; + city: string; + zipCode: number | null; +} +export interface Person { + name: string; + age: number; + address: Address; + email: string | null; +} +export interface Session { + id: number; + owner: Greeter; +} +export interface Measurement { + value: number; + precision: PrecisionTag; + optionalPrecision: PrecisionTag | null; +} +export interface ConfigStruct { +} +export interface Container { + object: any; + optionalObject: any | null; +} +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. + /// + /// Note: Calling this method will release the heap object and it will no longer be accessible. + release(): void; +} +export interface Greeter extends SwiftHeapObject { + greet(): string; + name: string; +} +export type Exports = { + Greeter: { + new(name: string): Greeter; + } + roundtrip(session: Person): Person; + roundtripContainer(container: Container): Container; + Precision: PrecisionObject + DataPoint: { + init(x: number, y: number, label: string, optCount: number | null, optFlag: boolean | null): DataPoint; + } + ConfigStruct: { + readonly maxRetries: number; + defaultConfig: string; + timeout: number; + readonly computedSetting: string; + update(timeout: number): number; + } +} +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/SwiftStruct.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js new file mode 100644 index 000000000..6f704013b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js @@ -0,0 +1,676 @@ +// 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 PrecisionValues = { + Rough: 0.1, + Fine: 0.001, +}; + +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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createDataPointHelpers = () => { + return () => ({ + lower: (value) => { + f64Stack.push(value.x); + f64Stack.push(value.y); + const bytes = textEncoder.encode(value.label); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const isSome = value.optCount != null; + if (isSome) { + i32Stack.push(value.optCount | 0); + } else { + i32Stack.push(0); + } + i32Stack.push(isSome ? 1 : 0); + const isSome1 = value.optFlag != null; + if (isSome1) { + i32Stack.push(value.optFlag ? 1 : 0); + } else { + i32Stack.push(0); + } + i32Stack.push(isSome1 ? 1 : 0); + return { cleanup: undefined }; + }, + lift: () => { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const bool = i32Stack.pop() !== 0; + optional = bool; + } else { + optional = null; + } + const isSome1 = i32Stack.pop(); + let optional1; + if (isSome1) { + const int = i32Stack.pop(); + optional1 = int; + } else { + optional1 = null; + } + const string = strStack.pop(); + const f64 = f64Stack.pop(); + const f641 = f64Stack.pop(); + return { x: f641, y: f64, label: string, optCount: optional1, optFlag: optional }; + } + }); + }; + const __bjs_createAddressHelpers = () => { + return () => ({ + lower: (value) => { + const bytes = textEncoder.encode(value.street); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + const bytes1 = textEncoder.encode(value.city); + const id1 = swift.memory.retain(bytes1); + i32Stack.push(bytes1.length); + i32Stack.push(id1); + const isSome = value.zipCode != null; + if (isSome) { + i32Stack.push(value.zipCode | 0); + } else { + i32Stack.push(0); + } + i32Stack.push(isSome ? 1 : 0); + return { cleanup: undefined }; + }, + lift: () => { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const int = i32Stack.pop(); + optional = int; + } else { + optional = null; + } + const string = strStack.pop(); + const string1 = strStack.pop(); + return { street: string1, city: string, zipCode: optional }; + } + }); + }; + const __bjs_createPersonHelpers = () => { + return () => ({ + lower: (value) => { + const bytes = textEncoder.encode(value.name); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + i32Stack.push((value.age | 0)); + const structResult = structHelpers.Address.lower(value.address); + const isSome = value.email != null; + let id1; + if (isSome) { + const bytes1 = textEncoder.encode(value.email); + id1 = swift.memory.retain(bytes1); + i32Stack.push(bytes1.length); + i32Stack.push(id1); + } else { + i32Stack.push(0); + i32Stack.push(0); + } + i32Stack.push(isSome ? 1 : 0); + const cleanup = () => { + if (structResult.cleanup) { structResult.cleanup(); } + }; + return { cleanup }; + }, + lift: () => { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const string = strStack.pop(); + optional = string; + } else { + optional = null; + } + const struct = structHelpers.Address.lift(); + const int = i32Stack.pop(); + const string1 = strStack.pop(); + return { name: string1, age: int, address: struct, email: optional }; + } + }); + }; + const __bjs_createSessionHelpers = () => { + return () => ({ + lower: (value) => { + i32Stack.push((value.id | 0)); + ptrStack.push(value.owner.pointer); + return { cleanup: undefined }; + }, + lift: () => { + const ptr = ptrStack.pop(); + const obj = _exports['Greeter'].__construct(ptr); + const int = i32Stack.pop(); + return { id: int, owner: obj }; + } + }); + }; + const __bjs_createMeasurementHelpers = () => { + return () => ({ + lower: (value) => { + f64Stack.push(value.value); + f32Stack.push(Math.fround(value.precision)); + const isSome = value.optionalPrecision != null; + if (isSome) { + f32Stack.push(Math.fround(value.optionalPrecision)); + } else { + f32Stack.push(0.0); + } + i32Stack.push(isSome ? 1 : 0); + return { cleanup: undefined }; + }, + lift: () => { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const rawValue = f32Stack.pop(); + optional = rawValue; + } else { + optional = null; + } + const rawValue1 = f32Stack.pop(); + const f64 = f64Stack.pop(); + return { value: f64, precision: rawValue1, optionalPrecision: optional }; + } + }); + }; + const __bjs_createConfigStructHelpers = () => { + return () => ({ + lower: (value) => { + return { cleanup: undefined }; + }, + lift: () => { + return { }; + } + }); + }; + const __bjs_createContainerHelpers = () => { + return () => ({ + lower: (value) => { + let id; + if (value.object != null) { + id = swift.memory.retain(value.object); + } else { + id = undefined; + } + i32Stack.push(id !== undefined ? id : 0); + const isSome = value.optionalObject != null; + let id1; + if (isSome) { + id1 = swift.memory.retain(value.optionalObject); + i32Stack.push(id1); + } else { + id1 = undefined; + i32Stack.push(0); + } + i32Stack.push(isSome ? 1 : 0); + return { cleanup: undefined }; + }, + lift: () => { + const isSome = i32Stack.pop(); + let optional; + if (isSome) { + const objectId = i32Stack.pop(); + let value; + if (objectId !== 0) { + value = swift.memory.getObject(objectId); + swift.memory.release(objectId); + } else { + value = null; + } + optional = value; + } else { + optional = null; + } + const objectId1 = i32Stack.pop(); + let value1; + if (objectId1 !== 0) { + value1 = swift.memory.getObject(objectId1); + swift.memory.release(objectId1); + } else { + value1 = null; + } + return { object: value1, optionalObject: optional }; + } + }); + }; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_struct_lower_DataPoint"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.DataPoint.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_DataPoint"] = function() { + const value = structHelpers.DataPoint.lift(); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_Address"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.Address.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_Address"] = function() { + const value = structHelpers.Address.lift(); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_Person"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.Person.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_Person"] = function() { + const value = structHelpers.Person.lift(); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_Session"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.Session.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_Session"] = function() { + const value = structHelpers.Session.lift(); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_Measurement"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.Measurement.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_Measurement"] = function() { + const value = structHelpers.Measurement.lift(); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_ConfigStruct"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.ConfigStruct.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_ConfigStruct"] = function() { + const value = structHelpers.ConfigStruct.lift(); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_Container"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.Container.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_Container"] = function() { + const value = structHelpers.Container.lift(); + 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_Greeter_wrap"] = function(pointer) { + const obj = _exports['Greeter'].__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; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.deinit(state.pointer); + }); + + /// 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); + const state = { pointer, deinit, hasReleased: false }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + return obj; + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.deinit(state.pointer); + } + } + class Greeter extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Greeter_deinit, Greeter.prototype); + } + + constructor(name) { + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + const ret = instance.exports.bjs_Greeter_init(nameId, nameBytes.length); + return Greeter.__construct(ret); + } + greet() { + instance.exports.bjs_Greeter_greet(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + get name() { + instance.exports.bjs_Greeter_name_get(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + set name(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_Greeter_name_set(this.pointer, valueId, valueBytes.length); + } + } + const DataPointHelpers = __bjs_createDataPointHelpers()(); + structHelpers.DataPoint = DataPointHelpers; + + const AddressHelpers = __bjs_createAddressHelpers()(); + structHelpers.Address = AddressHelpers; + + const PersonHelpers = __bjs_createPersonHelpers()(); + structHelpers.Person = PersonHelpers; + + const SessionHelpers = __bjs_createSessionHelpers()(); + structHelpers.Session = SessionHelpers; + + const MeasurementHelpers = __bjs_createMeasurementHelpers()(); + structHelpers.Measurement = MeasurementHelpers; + + const ConfigStructHelpers = __bjs_createConfigStructHelpers()(); + structHelpers.ConfigStruct = ConfigStructHelpers; + + const ContainerHelpers = __bjs_createContainerHelpers()(); + structHelpers.Container = ContainerHelpers; + + const exports = { + Greeter, + roundtrip: function bjs_roundtrip(session) { + const { cleanup: cleanup } = structHelpers.Person.lower(session); + instance.exports.bjs_roundtrip(); + const structValue = structHelpers.Person.lift(); + if (cleanup) { cleanup(); } + return structValue; + }, + roundtripContainer: function bjs_roundtripContainer(container) { + const { cleanup: cleanup } = structHelpers.Container.lower(container); + instance.exports.bjs_roundtripContainer(); + const structValue = structHelpers.Container.lift(); + if (cleanup) { cleanup(); } + return structValue; + }, + Precision: PrecisionValues, + DataPoint: { + init: function(x, y, label, optCount, optFlag) { + const labelBytes = textEncoder.encode(label); + const labelId = swift.memory.retain(labelBytes); + const isSome = optCount != null; + const isSome1 = optFlag != null; + instance.exports.bjs_DataPoint_init(x, y, labelId, labelBytes.length, +isSome, isSome ? optCount : 0, +isSome1, isSome1 ? optFlag : 0); + const structValue = structHelpers.DataPoint.lift(); + return structValue; + }, + }, + ConfigStruct: { + get maxRetries() { + const ret = instance.exports.bjs_ConfigStruct_static_maxRetries_get(); + return ret; + }, + get defaultConfig() { + instance.exports.bjs_ConfigStruct_static_defaultConfig_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + set defaultConfig(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_ConfigStruct_static_defaultConfig_set(valueId, valueBytes.length); + }, + get timeout() { + const ret = instance.exports.bjs_ConfigStruct_static_timeout_get(); + return ret; + }, + set timeout(value) { + instance.exports.bjs_ConfigStruct_static_timeout_set(value); + }, + get computedSetting() { + instance.exports.bjs_ConfigStruct_static_computedSetting_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + update: function(timeout) { + const ret = instance.exports.bjs_ConfigStruct_static_update(timeout); + return ret; + }, + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.d.ts new file mode 100644 index 000000000..3677f1e44 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.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.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js new file mode 100644 index 000000000..4962e659b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js @@ -0,0 +1,256 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createPointHelpers = () => { + return () => ({ + lower: (value) => { + i32Stack.push((value.x | 0)); + i32Stack.push((value.y | 0)); + return { cleanup: undefined }; + }, + lift: () => { + const int = i32Stack.pop(); + const int1 = i32Stack.pop(); + return { x: int1, y: int }; + } + }); + }; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_struct_lower_Point"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.Point.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_Point"] = function() { + const value = structHelpers.Point.lift(); + 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + 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()(); + 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 deleted file mode 100644 index 705c6a370..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js +++ /dev/null @@ -1,140 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_createTS2Skeleton"] = function bjs_createTS2Skeleton() { - try { - let ret = imports.createTS2Skeleton(); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_createCodeGenerator"] = function bjs_createCodeGenerator(format) { - try { - const formatObject = swift.memory.getObject(format); - swift.memory.release(format); - let ret = imports.createCodeGenerator(formatObject); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_TypeScriptProcessor_version_get"] = function bjs_TypeScriptProcessor_version_get(self) { - try { - let ret = swift.memory.getObject(self).version; - tmpRetBytes = textEncoder.encode(ret); - return tmpRetBytes.length; - } catch (error) { - setException(error); - } - } - TestModule["bjs_TypeScriptProcessor_convert"] = function bjs_TypeScriptProcessor_convert(self, ts) { - try { - const tsObject = swift.memory.getObject(ts); - swift.memory.release(ts); - let ret = swift.memory.getObject(self).convert(tsObject); - tmpRetBytes = textEncoder.encode(ret); - return tmpRetBytes.length; - } catch (error) { - setException(error); - } - } - TestModule["bjs_TypeScriptProcessor_validate"] = function bjs_TypeScriptProcessor_validate(self, ts) { - try { - const tsObject = swift.memory.getObject(ts); - swift.memory.release(ts); - let ret = swift.memory.getObject(self).validate(tsObject); - return ret !== 0; - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_CodeGenerator_outputFormat_get"] = function bjs_CodeGenerator_outputFormat_get(self) { - try { - let ret = swift.memory.getObject(self).outputFormat; - tmpRetBytes = textEncoder.encode(ret); - return tmpRetBytes.length; - } catch (error) { - setException(error); - } - } - TestModule["bjs_CodeGenerator_generate"] = function bjs_CodeGenerator_generate(self, input) { - try { - let ret = swift.memory.getObject(self).generate(swift.memory.getObject(input)); - tmpRetBytes = textEncoder.encode(ret); - return tmpRetBytes.length; - } 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; - - return { - - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.js deleted file mode 100644 index b2089962c..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.js +++ /dev/null @@ -1,79 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - - }, - 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; - - return { - throwsSomething: function bjs_throwsSomething() { - instance.exports.bjs_throwsSomething(); - if (tmpRetException) { - const error = swift.memory.getObject(tmpRetException); - swift.memory.release(tmpRetException); - tmpRetException = undefined; - throw error; - } - }, - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.d.ts similarity index 100% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.d.ts rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.d.ts diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js new file mode 100644 index 000000000..3726a48ae --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js @@ -0,0 +1,225 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + }, + 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 = { + throwsSomething: function bjs_throwsSomething() { + instance.exports.bjs_throwsSomething(); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.d.ts deleted file mode 100644 index da5dfb076..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -// 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 type Exports = { -} -export type Imports = { - checkSimple(a: number): void; -} -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/TypeAlias.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.js deleted file mode 100644 index 2eb9dee50..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.js +++ /dev/null @@ -1,78 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_checkSimple"] = function bjs_checkSimple(a) { - try { - imports.checkSimple(a); - } 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; - - return { - - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js deleted file mode 100644 index c7d622ea0..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js +++ /dev/null @@ -1,127 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_Greeter_init"] = function bjs_Greeter_init(name) { - try { - const nameObject = swift.memory.getObject(name); - swift.memory.release(name); - let ret = new imports.Greeter(nameObject); - return swift.memory.retain(ret); - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_Greeter_name_get"] = function bjs_Greeter_name_get(self) { - try { - let ret = swift.memory.getObject(self).name; - tmpRetBytes = textEncoder.encode(ret); - return tmpRetBytes.length; - } catch (error) { - setException(error); - } - } - TestModule["bjs_Greeter_name_set"] = function bjs_Greeter_name_set(self, newValue) { - try { - const newValueObject = swift.memory.getObject(newValue); - swift.memory.release(newValue); - swift.memory.getObject(self).name = newValueObject; - } catch (error) { - setException(error); - } - } - TestModule["bjs_Greeter_age_get"] = function bjs_Greeter_age_get(self) { - try { - let ret = swift.memory.getObject(self).age; - return ret; - } catch (error) { - setException(error); - return 0 - } - } - TestModule["bjs_Greeter_greet"] = function bjs_Greeter_greet(self) { - try { - let ret = swift.memory.getObject(self).greet(); - tmpRetBytes = textEncoder.encode(ret); - return tmpRetBytes.length; - } catch (error) { - setException(error); - } - } - TestModule["bjs_Greeter_changeName"] = function bjs_Greeter_changeName(self, name) { - try { - const nameObject = swift.memory.getObject(name); - swift.memory.release(name); - swift.memory.getObject(self).changeName(nameObject); - } 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; - - return { - - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.d.ts new file mode 100644 index 000000000..4f9aa4e4a --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.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.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js new file mode 100644 index 000000000..7c3627d13 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js @@ -0,0 +1,299 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createPointerFieldsHelpers = () => { + return () => ({ + lower: (value) => { + ptrStack.push((value.raw | 0)); + ptrStack.push((value.mutRaw | 0)); + ptrStack.push((value.opaque | 0)); + ptrStack.push((value.ptr | 0)); + ptrStack.push((value.mutPtr | 0)); + return { cleanup: undefined }; + }, + lift: () => { + const pointer = ptrStack.pop(); + const pointer1 = ptrStack.pop(); + const pointer2 = ptrStack.pop(); + const pointer3 = ptrStack.pop(); + const pointer4 = ptrStack.pop(); + return { raw: pointer4, mutRaw: pointer3, opaque: pointer2, ptr: pointer1, mutPtr: pointer }; + } + }); + }; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_struct_lower_PointerFields"] = function(objectId) { + const { cleanup: cleanup } = structHelpers.PointerFields.lower(swift.memory.getObject(objectId)); + if (cleanup) { + return tmpStructCleanups.push(cleanup); + } + return 0; + } + bjs["swift_js_struct_lift_PointerFields"] = function() { + const value = structHelpers.PointerFields.lift(); + 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + }, + 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()(); + 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(); + 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(); + 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 deleted file mode 100644 index c200c077d..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Export.js +++ /dev/null @@ -1,73 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - - }, - 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; - - return { - check: function bjs_check() { - instance.exports.bjs_check(); - }, - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.d.ts deleted file mode 100644 index 8cd1e806e..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -// 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 type Exports = { -} -export type Imports = { - check(): void; -} -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/VoidParameterVoidReturn.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.js deleted file mode 100644 index ca4976888..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.js +++ /dev/null @@ -1,78 +0,0 @@ -// 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; - return { - /** - * @param {WebAssembly.Imports} importObject - */ - addImports: (importObject, importsContext) => { - const 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); - } - - const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_check"] = function bjs_check() { - try { - imports.check(); - } 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; - - return { - - }; - }, - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.d.ts similarity index 96% rename from Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Export.d.ts rename to Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.d.ts index be85a00fd..7acba67a0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.d.ts @@ -8,6 +8,7 @@ export type Exports = { check(): void; } export type Imports = { + check(): void; } export function createInstantiator(options: { imports: Imports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js new file mode 100644 index 000000000..e338c840d --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js @@ -0,0 +1,228 @@ +// 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 strStack = []; + let i32Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let tmpStructCleanups = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + + 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); + swift.memory.release(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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_struct_cleanup"] = function(cleanupId) { + if (cleanupId === 0) { return; } + const index = (cleanupId | 0) - 1; + const cleanup = tmpStructCleanups[index]; + tmpStructCleanups[index] = null; + if (cleanup) { cleanup(); } + while (tmpStructCleanups.length > 0 && tmpStructCleanups[tmpStructCleanups.length - 1] == null) { + tmpStructCleanups.pop(); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } 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; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_check"] = function bjs_check() { + try { + imports.check(); + } 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 = { + check: function bjs_check() { + instance.exports.bjs_check(); + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/tsconfig.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/tsconfig.json new file mode 100644 index 000000000..277b2c578 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "strict": true, + "noEmit": true, + "skipLibCheck": false, + "target": "ES2020", + "module": "ES2020", + "moduleResolution": "node", + "lib": ["ES2020", "DOM"] + }, + "include": ["*.d.ts"] +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Async.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Async.json deleted file mode 100644 index 8e7154516..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Async.json +++ /dev/null @@ -1,168 +0,0 @@ -{ - "classes" : [ - - ], - "functions" : [ - { - "abiName" : "bjs_asyncReturnVoid", - "effects" : { - "isAsync" : true, - "isThrows" : false - }, - "name" : "asyncReturnVoid", - "parameters" : [ - - ], - "returnType" : { - "void" : { - - } - } - }, - { - "abiName" : "bjs_asyncRoundTripInt", - "effects" : { - "isAsync" : true, - "isThrows" : false - }, - "name" : "asyncRoundTripInt", - "parameters" : [ - { - "label" : "_", - "name" : "v", - "type" : { - "int" : { - - } - } - } - ], - "returnType" : { - "int" : { - - } - } - }, - { - "abiName" : "bjs_asyncRoundTripString", - "effects" : { - "isAsync" : true, - "isThrows" : false - }, - "name" : "asyncRoundTripString", - "parameters" : [ - { - "label" : "_", - "name" : "v", - "type" : { - "string" : { - - } - } - } - ], - "returnType" : { - "string" : { - - } - } - }, - { - "abiName" : "bjs_asyncRoundTripBool", - "effects" : { - "isAsync" : true, - "isThrows" : false - }, - "name" : "asyncRoundTripBool", - "parameters" : [ - { - "label" : "_", - "name" : "v", - "type" : { - "bool" : { - - } - } - } - ], - "returnType" : { - "bool" : { - - } - } - }, - { - "abiName" : "bjs_asyncRoundTripFloat", - "effects" : { - "isAsync" : true, - "isThrows" : false - }, - "name" : "asyncRoundTripFloat", - "parameters" : [ - { - "label" : "_", - "name" : "v", - "type" : { - "float" : { - - } - } - } - ], - "returnType" : { - "float" : { - - } - } - }, - { - "abiName" : "bjs_asyncRoundTripDouble", - "effects" : { - "isAsync" : true, - "isThrows" : false - }, - "name" : "asyncRoundTripDouble", - "parameters" : [ - { - "label" : "_", - "name" : "v", - "type" : { - "double" : { - - } - } - } - ], - "returnType" : { - "double" : { - - } - } - }, - { - "abiName" : "bjs_asyncRoundTripJSObject", - "effects" : { - "isAsync" : true, - "isThrows" : false - }, - "name" : "asyncRoundTripJSObject", - "parameters" : [ - { - "label" : "_", - "name" : "v", - "type" : { - "jsObject" : { - - } - } - } - ], - "returnType" : { - "jsObject" : { - - } - } - } - ], - "moduleName" : "TestModule" -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Async.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Async.swift deleted file mode 100644 index 10a3a24d9..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Async.swift +++ /dev/null @@ -1,102 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -@_expose(wasm, "bjs_asyncReturnVoid") -@_cdecl("bjs_asyncReturnVoid") -public func _bjs_asyncReturnVoid() -> Int32 { - #if arch(wasm32) - let ret = JSPromise.async { - await asyncReturnVoid() - } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_asyncRoundTripInt") -@_cdecl("bjs_asyncRoundTripInt") -public func _bjs_asyncRoundTripInt(v: Int32) -> Int32 { - #if arch(wasm32) - let ret = JSPromise.async { - return await asyncRoundTripInt(_: Int(v)).jsValue - } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_asyncRoundTripString") -@_cdecl("bjs_asyncRoundTripString") -public func _bjs_asyncRoundTripString(vBytes: Int32, vLen: Int32) -> Int32 { - #if arch(wasm32) - let ret = JSPromise.async { - let v = String(unsafeUninitializedCapacity: Int(vLen)) { b in - _swift_js_init_memory(vBytes, b.baseAddress.unsafelyUnwrapped) - return Int(vLen) - } - return await asyncRoundTripString(_: v).jsValue - } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_asyncRoundTripBool") -@_cdecl("bjs_asyncRoundTripBool") -public func _bjs_asyncRoundTripBool(v: Int32) -> Int32 { - #if arch(wasm32) - let ret = JSPromise.async { - return await asyncRoundTripBool(_: v == 1).jsValue - } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_asyncRoundTripFloat") -@_cdecl("bjs_asyncRoundTripFloat") -public func _bjs_asyncRoundTripFloat(v: Float32) -> Int32 { - #if arch(wasm32) - let ret = JSPromise.async { - return await asyncRoundTripFloat(_: v).jsValue - } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_asyncRoundTripDouble") -@_cdecl("bjs_asyncRoundTripDouble") -public func _bjs_asyncRoundTripDouble(v: Float64) -> Int32 { - #if arch(wasm32) - let ret = JSPromise.async { - return await asyncRoundTripDouble(_: v).jsValue - } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_asyncRoundTripJSObject") -@_cdecl("bjs_asyncRoundTripJSObject") -public func _bjs_asyncRoundTripJSObject(v: Int32) -> Int32 { - #if arch(wasm32) - let ret = JSPromise.async { - return await asyncRoundTripJSObject(_: JSObject(id: UInt32(bitPattern: v))).jsValue - } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.json deleted file mode 100644 index 1d1b0fbef..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.json +++ /dev/null @@ -1,154 +0,0 @@ -{ - "classes" : [ - { - "constructor" : { - "abiName" : "bjs_Greeter_init", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "parameters" : [ - { - "label" : "name", - "name" : "name", - "type" : { - "string" : { - - } - } - } - ] - }, - "methods" : [ - { - "abiName" : "bjs_Greeter_greet", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "greet", - "parameters" : [ - - ], - "returnType" : { - "string" : { - - } - } - } - ], - "name" : "Greeter", - "namespace" : [ - "__Swift", - "Foundation" - ] - }, - { - "constructor" : { - "abiName" : "bjs_Converter_init", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "parameters" : [ - - ] - }, - "methods" : [ - { - "abiName" : "bjs_Converter_toString", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "toString", - "parameters" : [ - { - "label" : "value", - "name" : "value", - "type" : { - "int" : { - - } - } - } - ], - "returnType" : { - "string" : { - - } - } - } - ], - "name" : "Converter", - "namespace" : [ - "Utils", - "Converters" - ] - }, - { - "methods" : [ - { - "abiName" : "bjs_UUID_uuidString", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "uuidString", - "parameters" : [ - - ], - "returnType" : { - "string" : { - - } - } - } - ], - "name" : "UUID", - "namespace" : [ - "__Swift", - "Foundation" - ] - } - ], - "functions" : [ - { - "abiName" : "bjs_plainFunction", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "plainFunction", - "parameters" : [ - - ], - "returnType" : { - "string" : { - - } - } - }, - { - "abiName" : "bjs_namespacedFunction", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "namespacedFunction", - "namespace" : [ - "MyModule", - "Utils" - ], - "parameters" : [ - - ], - "returnType" : { - "string" : { - - } - } - } - ], - "moduleName" : "TestModule" -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.swift deleted file mode 100644 index 21937c6cd..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.swift +++ /dev/null @@ -1,140 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -@_expose(wasm, "bjs_plainFunction") -@_cdecl("bjs_plainFunction") -public func _bjs_plainFunction() -> Void { - #if arch(wasm32) - var ret = plainFunction() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_namespacedFunction") -@_cdecl("bjs_namespacedFunction") -public func _bjs_namespacedFunction() -> Void { - #if arch(wasm32) - var ret = namespacedFunction() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_Greeter_init") -@_cdecl("bjs_Greeter_init") -public func _bjs_Greeter_init(nameBytes: Int32, nameLen: Int32) -> UnsafeMutableRawPointer { - #if arch(wasm32) - let name = String(unsafeUninitializedCapacity: Int(nameLen)) { b in - _swift_js_init_memory(nameBytes, b.baseAddress.unsafelyUnwrapped) - return Int(nameLen) - } - let ret = Greeter(name: name) - return Unmanaged.passRetained(ret).toOpaque() - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_Greeter_greet") -@_cdecl("bjs_Greeter_greet") -public func _bjs_Greeter_greet(_self: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().greet() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_Greeter_deinit") -@_cdecl("bjs_Greeter_deinit") -public func _bjs_Greeter_deinit(pointer: UnsafeMutableRawPointer) { - Unmanaged.fromOpaque(pointer).release() -} - -extension Greeter: ConvertibleToJSValue { - var jsValue: JSValue { - @_extern(wasm, module: "TestModule", name: "bjs_Greeter_wrap") - func _bjs_Greeter_wrap(_: UnsafeMutableRawPointer) -> Int32 - return .object(JSObject(id: UInt32(bitPattern: _bjs_Greeter_wrap(Unmanaged.passRetained(self).toOpaque())))) - } -} - -@_expose(wasm, "bjs_Converter_init") -@_cdecl("bjs_Converter_init") -public func _bjs_Converter_init() -> UnsafeMutableRawPointer { - #if arch(wasm32) - let ret = Converter() - return Unmanaged.passRetained(ret).toOpaque() - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_Converter_toString") -@_cdecl("bjs_Converter_toString") -public func _bjs_Converter_toString(_self: UnsafeMutableRawPointer, value: Int32) -> Void { - #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().toString(value: Int(value)) - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_Converter_deinit") -@_cdecl("bjs_Converter_deinit") -public func _bjs_Converter_deinit(pointer: UnsafeMutableRawPointer) { - Unmanaged.fromOpaque(pointer).release() -} - -extension Converter: ConvertibleToJSValue { - var jsValue: JSValue { - @_extern(wasm, module: "TestModule", name: "bjs_Converter_wrap") - func _bjs_Converter_wrap(_: UnsafeMutableRawPointer) -> Int32 - return .object(JSObject(id: UInt32(bitPattern: _bjs_Converter_wrap(Unmanaged.passRetained(self).toOpaque())))) - } -} - -@_expose(wasm, "bjs_UUID_uuidString") -@_cdecl("bjs_UUID_uuidString") -public func _bjs_UUID_uuidString(_self: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().uuidString() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_UUID_deinit") -@_cdecl("bjs_UUID_deinit") -public func _bjs_UUID_deinit(pointer: UnsafeMutableRawPointer) { - Unmanaged.fromOpaque(pointer).release() -} - -extension UUID: ConvertibleToJSValue { - var jsValue: JSValue { - @_extern(wasm, module: "TestModule", name: "bjs_UUID_wrap") - func _bjs_UUID_wrap(_: UnsafeMutableRawPointer) -> Int32 - return .object(JSObject(id: UInt32(bitPattern: _bjs_UUID_wrap(Unmanaged.passRetained(self).toOpaque())))) - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.json deleted file mode 100644 index 7ba4d9dcf..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "classes" : [ - - ], - "functions" : [ - { - "abiName" : "bjs_check", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "check", - "parameters" : [ - { - "label" : "a", - "name" : "a", - "type" : { - "int" : { - - } - } - }, - { - "label" : "b", - "name" : "b", - "type" : { - "float" : { - - } - } - }, - { - "label" : "c", - "name" : "c", - "type" : { - "double" : { - - } - } - }, - { - "label" : "d", - "name" : "d", - "type" : { - "bool" : { - - } - } - } - ], - "returnType" : { - "void" : { - - } - } - } - ], - "moduleName" : "TestModule" -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.swift deleted file mode 100644 index c686c4267..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.swift +++ /dev/null @@ -1,17 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -@_expose(wasm, "bjs_check") -@_cdecl("bjs_check") -public func _bjs_check(a: Int32, b: Float32, c: Float64, d: Int32) -> Void { - #if arch(wasm32) - check(a: Int(a), b: b, c: c, d: d == 1) - #else - fatalError("Only available on WebAssembly") - #endif -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.json deleted file mode 100644 index 54e00ea5c..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "classes" : [ - - ], - "functions" : [ - { - "abiName" : "bjs_checkInt", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "checkInt", - "parameters" : [ - - ], - "returnType" : { - "int" : { - - } - } - }, - { - "abiName" : "bjs_checkFloat", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "checkFloat", - "parameters" : [ - - ], - "returnType" : { - "float" : { - - } - } - }, - { - "abiName" : "bjs_checkDouble", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "checkDouble", - "parameters" : [ - - ], - "returnType" : { - "double" : { - - } - } - }, - { - "abiName" : "bjs_checkBool", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "checkBool", - "parameters" : [ - - ], - "returnType" : { - "bool" : { - - } - } - } - ], - "moduleName" : "TestModule" -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.swift deleted file mode 100644 index 7356f2c85..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.swift +++ /dev/null @@ -1,51 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -@_expose(wasm, "bjs_checkInt") -@_cdecl("bjs_checkInt") -public func _bjs_checkInt() -> Int32 { - #if arch(wasm32) - let ret = checkInt() - return Int32(ret) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_checkFloat") -@_cdecl("bjs_checkFloat") -public func _bjs_checkFloat() -> Float32 { - #if arch(wasm32) - let ret = checkFloat() - return Float32(ret) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_checkDouble") -@_cdecl("bjs_checkDouble") -public func _bjs_checkDouble() -> Float64 { - #if arch(wasm32) - let ret = checkDouble() - return Float64(ret) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_checkBool") -@_cdecl("bjs_checkBool") -public func _bjs_checkBool() -> Int32 { - #if arch(wasm32) - let ret = checkBool() - return Int32(ret ? 1 : 0) - #else - fatalError("Only available on WebAssembly") - #endif -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.json deleted file mode 100644 index c2286d122..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "classes" : [ - - ], - "functions" : [ - { - "abiName" : "bjs_checkString", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "checkString", - "parameters" : [ - { - "label" : "a", - "name" : "a", - "type" : { - "string" : { - - } - } - } - ], - "returnType" : { - "void" : { - - } - } - } - ], - "moduleName" : "TestModule" -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.swift deleted file mode 100644 index 69bd66b5c..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.swift +++ /dev/null @@ -1,21 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -@_expose(wasm, "bjs_checkString") -@_cdecl("bjs_checkString") -public func _bjs_checkString(aBytes: Int32, aLen: Int32) -> Void { - #if arch(wasm32) - let a = String(unsafeUninitializedCapacity: Int(aLen)) { b in - _swift_js_init_memory(aBytes, b.baseAddress.unsafelyUnwrapped) - return Int(aLen) - } - checkString(a: a) - #else - fatalError("Only available on WebAssembly") - #endif -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringReturn.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringReturn.json deleted file mode 100644 index 23331875f..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringReturn.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "classes" : [ - - ], - "functions" : [ - { - "abiName" : "bjs_checkString", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "checkString", - "parameters" : [ - - ], - "returnType" : { - "string" : { - - } - } - } - ], - "moduleName" : "TestModule" -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringReturn.swift deleted file mode 100644 index 536f06230..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringReturn.swift +++ /dev/null @@ -1,20 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -@_expose(wasm, "bjs_checkString") -@_cdecl("bjs_checkString") -public func _bjs_checkString() -> Void { - #if arch(wasm32) - var ret = checkString() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - #else - fatalError("Only available on WebAssembly") - #endif -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClass.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClass.json deleted file mode 100644 index 489f1cd5b..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClass.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "classes" : [ - { - "constructor" : { - "abiName" : "bjs_Greeter_init", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "parameters" : [ - { - "label" : "name", - "name" : "name", - "type" : { - "string" : { - - } - } - } - ] - }, - "methods" : [ - { - "abiName" : "bjs_Greeter_greet", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "greet", - "parameters" : [ - - ], - "returnType" : { - "string" : { - - } - } - }, - { - "abiName" : "bjs_Greeter_changeName", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "changeName", - "parameters" : [ - { - "label" : "name", - "name" : "name", - "type" : { - "string" : { - - } - } - } - ], - "returnType" : { - "void" : { - - } - } - } - ], - "name" : "Greeter" - } - ], - "functions" : [ - { - "abiName" : "bjs_takeGreeter", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "takeGreeter", - "parameters" : [ - { - "label" : "greeter", - "name" : "greeter", - "type" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } - } - } - ], - "returnType" : { - "void" : { - - } - } - } - ], - "moduleName" : "TestModule" -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClass.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClass.swift deleted file mode 100644 index 09589de31..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClass.swift +++ /dev/null @@ -1,73 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -@_expose(wasm, "bjs_takeGreeter") -@_cdecl("bjs_takeGreeter") -public func _bjs_takeGreeter(greeter: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - takeGreeter(greeter: Unmanaged.fromOpaque(greeter).takeUnretainedValue()) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_Greeter_init") -@_cdecl("bjs_Greeter_init") -public func _bjs_Greeter_init(nameBytes: Int32, nameLen: Int32) -> UnsafeMutableRawPointer { - #if arch(wasm32) - let name = String(unsafeUninitializedCapacity: Int(nameLen)) { b in - _swift_js_init_memory(nameBytes, b.baseAddress.unsafelyUnwrapped) - return Int(nameLen) - } - let ret = Greeter(name: name) - return Unmanaged.passRetained(ret).toOpaque() - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_Greeter_greet") -@_cdecl("bjs_Greeter_greet") -public func _bjs_Greeter_greet(_self: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().greet() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_Greeter_changeName") -@_cdecl("bjs_Greeter_changeName") -public func _bjs_Greeter_changeName(_self: UnsafeMutableRawPointer, nameBytes: Int32, nameLen: Int32) -> Void { - #if arch(wasm32) - let name = String(unsafeUninitializedCapacity: Int(nameLen)) { b in - _swift_js_init_memory(nameBytes, b.baseAddress.unsafelyUnwrapped) - return Int(nameLen) - } - Unmanaged.fromOpaque(_self).takeUnretainedValue().changeName(name: name) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_Greeter_deinit") -@_cdecl("bjs_Greeter_deinit") -public func _bjs_Greeter_deinit(pointer: UnsafeMutableRawPointer) { - Unmanaged.fromOpaque(pointer).release() -} - -extension Greeter: ConvertibleToJSValue { - var jsValue: JSValue { - @_extern(wasm, module: "TestModule", name: "bjs_Greeter_wrap") - func _bjs_Greeter_wrap(_: UnsafeMutableRawPointer) -> Int32 - return .object(JSObject(id: UInt32(bitPattern: _bjs_Greeter_wrap(Unmanaged.passRetained(self).toOpaque())))) - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Throws.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Throws.json deleted file mode 100644 index 9acf5b201..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Throws.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "classes" : [ - - ], - "functions" : [ - { - "abiName" : "bjs_throwsSomething", - "effects" : { - "isAsync" : false, - "isThrows" : true - }, - "name" : "throwsSomething", - "parameters" : [ - - ], - "returnType" : { - "void" : { - - } - } - } - ], - "moduleName" : "TestModule" -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/VoidParameterVoidReturn.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/VoidParameterVoidReturn.json deleted file mode 100644 index 12c735315..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/VoidParameterVoidReturn.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "classes" : [ - - ], - "functions" : [ - { - "abiName" : "bjs_check", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "check", - "parameters" : [ - - ], - "returnType" : { - "void" : { - - } - } - } - ], - "moduleName" : "TestModule" -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/VoidParameterVoidReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/VoidParameterVoidReturn.swift deleted file mode 100644 index 15e91a0b8..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/VoidParameterVoidReturn.swift +++ /dev/null @@ -1,17 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -@_expose(wasm, "bjs_check") -@_cdecl("bjs_check") -public func _bjs_check() -> Void { - #if arch(wasm32) - check() - #else - fatalError("Only available on WebAssembly") - #endif -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/ArrayParameter.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/ArrayParameter.swift deleted file mode 100644 index 34841ae86..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/ArrayParameter.swift +++ /dev/null @@ -1,52 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -func checkArray(_ a: JSObject) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_checkArray") - func bjs_checkArray(_ a: Int32) -> Void - #else - func bjs_checkArray(_ a: Int32) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - bjs_checkArray(Int32(bitPattern: a.id)) - if let error = _swift_js_take_exception() { - throw error - } -} - -func checkArrayWithLength(_ a: JSObject, _ b: Double) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_checkArrayWithLength") - func bjs_checkArrayWithLength(_ a: Int32, _ b: Float64) -> Void - #else - func bjs_checkArrayWithLength(_ a: Int32, _ b: Float64) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - bjs_checkArrayWithLength(Int32(bitPattern: a.id), b) - if let error = _swift_js_take_exception() { - throw error - } -} - -func checkArray(_ a: JSObject) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_checkArray") - func bjs_checkArray(_ a: Int32) -> Void - #else - func bjs_checkArray(_ a: Int32) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - bjs_checkArray(Int32(bitPattern: a.id)) - if let error = _swift_js_take_exception() { - throw error - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/Async.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/Async.swift deleted file mode 100644 index aa11cd0c1..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/Async.swift +++ /dev/null @@ -1,123 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -func asyncReturnVoid() throws(JSException) -> JSPromise { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_asyncReturnVoid") - func bjs_asyncReturnVoid() -> Int32 - #else - func bjs_asyncReturnVoid() -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_asyncReturnVoid() - if let error = _swift_js_take_exception() { - throw error - } - return JSPromise(takingThis: ret) -} - -func asyncRoundTripInt(_ v: Double) throws(JSException) -> JSPromise { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_asyncRoundTripInt") - func bjs_asyncRoundTripInt(_ v: Float64) -> Int32 - #else - func bjs_asyncRoundTripInt(_ v: Float64) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_asyncRoundTripInt(v) - if let error = _swift_js_take_exception() { - throw error - } - return JSPromise(takingThis: ret) -} - -func asyncRoundTripString(_ v: String) throws(JSException) -> JSPromise { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_asyncRoundTripString") - func bjs_asyncRoundTripString(_ v: Int32) -> Int32 - #else - func bjs_asyncRoundTripString(_ v: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - var v = v - let vId = v.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_asyncRoundTripString(vId) - if let error = _swift_js_take_exception() { - throw error - } - return JSPromise(takingThis: ret) -} - -func asyncRoundTripBool(_ v: Bool) throws(JSException) -> JSPromise { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_asyncRoundTripBool") - func bjs_asyncRoundTripBool(_ v: Int32) -> Int32 - #else - func bjs_asyncRoundTripBool(_ v: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_asyncRoundTripBool(Int32(v ? 1 : 0)) - if let error = _swift_js_take_exception() { - throw error - } - return JSPromise(takingThis: ret) -} - -func asyncRoundTripFloat(_ v: Double) throws(JSException) -> JSPromise { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_asyncRoundTripFloat") - func bjs_asyncRoundTripFloat(_ v: Float64) -> Int32 - #else - func bjs_asyncRoundTripFloat(_ v: Float64) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_asyncRoundTripFloat(v) - if let error = _swift_js_take_exception() { - throw error - } - return JSPromise(takingThis: ret) -} - -func asyncRoundTripDouble(_ v: Double) throws(JSException) -> JSPromise { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_asyncRoundTripDouble") - func bjs_asyncRoundTripDouble(_ v: Float64) -> Int32 - #else - func bjs_asyncRoundTripDouble(_ v: Float64) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_asyncRoundTripDouble(v) - if let error = _swift_js_take_exception() { - throw error - } - return JSPromise(takingThis: ret) -} - -func asyncRoundTripJSObject(_ v: JSObject) throws(JSException) -> JSPromise { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_asyncRoundTripJSObject") - func bjs_asyncRoundTripJSObject(_ v: Int32) -> Int32 - #else - func bjs_asyncRoundTripJSObject(_ v: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_asyncRoundTripJSObject(Int32(bitPattern: v.id)) - if let error = _swift_js_take_exception() { - throw error - } - return JSPromise(takingThis: ret) -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/Interface.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/Interface.swift deleted file mode 100644 index be9f524ee..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/Interface.swift +++ /dev/null @@ -1,68 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -func returnAnimatable() throws(JSException) -> Animatable { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_returnAnimatable") - func bjs_returnAnimatable() -> Int32 - #else - func bjs_returnAnimatable() -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_returnAnimatable() - if let error = _swift_js_take_exception() { - throw error - } - return Animatable(takingThis: ret) -} - -struct Animatable { - let this: JSObject - - init(this: JSObject) { - self.this = this - } - - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) - } - - func animate(_ keyframes: JSObject, _ options: JSObject) throws(JSException) -> JSObject { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_Animatable_animate") - func bjs_Animatable_animate(_ self: Int32, _ keyframes: Int32, _ options: Int32) -> Int32 - #else - func bjs_Animatable_animate(_ self: Int32, _ keyframes: Int32, _ options: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_Animatable_animate(Int32(bitPattern: self.this.id), Int32(bitPattern: keyframes.id), Int32(bitPattern: options.id)) - if let error = _swift_js_take_exception() { - throw error - } - return JSObject(id: UInt32(bitPattern: ret)) - } - - func getAnimations(_ options: JSObject) throws(JSException) -> JSObject { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_Animatable_getAnimations") - func bjs_Animatable_getAnimations(_ self: Int32, _ options: Int32) -> Int32 - #else - func bjs_Animatable_getAnimations(_ self: Int32, _ options: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_Animatable_getAnimations(Int32(bitPattern: self.this.id), Int32(bitPattern: options.id)) - if let error = _swift_js_take_exception() { - throw error - } - return JSObject(id: UInt32(bitPattern: ret)) - } - -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/MultipleImportedTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/MultipleImportedTypes.swift deleted file mode 100644 index d3e06e810..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/MultipleImportedTypes.swift +++ /dev/null @@ -1,307 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -func createDatabaseConnection(_ config: JSObject) throws(JSException) -> DatabaseConnection { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_createDatabaseConnection") - func bjs_createDatabaseConnection(_ config: Int32) -> Int32 - #else - func bjs_createDatabaseConnection(_ config: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_createDatabaseConnection(Int32(bitPattern: config.id)) - if let error = _swift_js_take_exception() { - throw error - } - return DatabaseConnection(takingThis: ret) -} - -func createLogger(_ level: String) throws(JSException) -> Logger { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_createLogger") - func bjs_createLogger(_ level: Int32) -> Int32 - #else - func bjs_createLogger(_ level: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - var level = level - let levelId = level.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_createLogger(levelId) - if let error = _swift_js_take_exception() { - throw error - } - return Logger(takingThis: ret) -} - -func getConfigManager() throws(JSException) -> ConfigManager { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_getConfigManager") - func bjs_getConfigManager() -> Int32 - #else - func bjs_getConfigManager() -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_getConfigManager() - if let error = _swift_js_take_exception() { - throw error - } - return ConfigManager(takingThis: ret) -} - -struct DatabaseConnection { - let this: JSObject - - init(this: JSObject) { - self.this = this - } - - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) - } - - var isConnected: Bool { - get throws(JSException) { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_DatabaseConnection_isConnected_get") - func bjs_DatabaseConnection_isConnected_get(_ self: Int32) -> Int32 - #else - func bjs_DatabaseConnection_isConnected_get(_ self: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_DatabaseConnection_isConnected_get(Int32(bitPattern: self.this.id)) - if let error = _swift_js_take_exception() { - throw error - } - return ret == 1 - } - } - - var connectionTimeout: Double { - get throws(JSException) { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_DatabaseConnection_connectionTimeout_get") - func bjs_DatabaseConnection_connectionTimeout_get(_ self: Int32) -> Float64 - #else - func bjs_DatabaseConnection_connectionTimeout_get(_ self: Int32) -> Float64 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_DatabaseConnection_connectionTimeout_get(Int32(bitPattern: self.this.id)) - if let error = _swift_js_take_exception() { - throw error - } - return Double(ret) - } - } - - func setConnectionTimeout(_ newValue: Double) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_DatabaseConnection_connectionTimeout_set") - func bjs_DatabaseConnection_connectionTimeout_set(_ self: Int32, _ newValue: Float64) -> Void - #else - func bjs_DatabaseConnection_connectionTimeout_set(_ self: Int32, _ newValue: Float64) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - bjs_DatabaseConnection_connectionTimeout_set(Int32(bitPattern: self.this.id), newValue) - if let error = _swift_js_take_exception() { - throw error - } - } - - func connect(_ url: String) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_DatabaseConnection_connect") - func bjs_DatabaseConnection_connect(_ self: Int32, _ url: Int32) -> Void - #else - func bjs_DatabaseConnection_connect(_ self: Int32, _ url: Int32) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - var url = url - let urlId = url.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_DatabaseConnection_connect(Int32(bitPattern: self.this.id), urlId) - if let error = _swift_js_take_exception() { - throw error - } - } - - func execute(_ query: String) throws(JSException) -> JSObject { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_DatabaseConnection_execute") - func bjs_DatabaseConnection_execute(_ self: Int32, _ query: Int32) -> Int32 - #else - func bjs_DatabaseConnection_execute(_ self: Int32, _ query: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - var query = query - let queryId = query.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_DatabaseConnection_execute(Int32(bitPattern: self.this.id), queryId) - if let error = _swift_js_take_exception() { - throw error - } - return JSObject(id: UInt32(bitPattern: ret)) - } - -} - -struct Logger { - let this: JSObject - - init(this: JSObject) { - self.this = this - } - - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) - } - - var level: String { - get throws(JSException) { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_Logger_level_get") - func bjs_Logger_level_get(_ self: Int32) -> Int32 - #else - func bjs_Logger_level_get(_ self: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_Logger_level_get(Int32(bitPattern: self.this.id)) - if let error = _swift_js_take_exception() { - throw error - } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } - } - } - - func log(_ message: String) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_Logger_log") - func bjs_Logger_log(_ self: Int32, _ message: Int32) -> Void - #else - func bjs_Logger_log(_ self: Int32, _ message: Int32) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - var message = message - let messageId = message.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_Logger_log(Int32(bitPattern: self.this.id), messageId) - if let error = _swift_js_take_exception() { - throw error - } - } - - func error(_ message: String, _ error: JSObject) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_Logger_error") - func bjs_Logger_error(_ self: Int32, _ message: Int32, _ error: Int32) -> Void - #else - func bjs_Logger_error(_ self: Int32, _ message: Int32, _ error: Int32) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - var message = message - let messageId = message.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_Logger_error(Int32(bitPattern: self.this.id), messageId, Int32(bitPattern: error.id)) - if let error = _swift_js_take_exception() { - throw error - } - } - -} - -struct ConfigManager { - let this: JSObject - - init(this: JSObject) { - self.this = this - } - - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) - } - - var configPath: String { - get throws(JSException) { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_ConfigManager_configPath_get") - func bjs_ConfigManager_configPath_get(_ self: Int32) -> Int32 - #else - func bjs_ConfigManager_configPath_get(_ self: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_ConfigManager_configPath_get(Int32(bitPattern: self.this.id)) - if let error = _swift_js_take_exception() { - throw error - } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } - } - } - - func get(_ key: String) throws(JSException) -> JSObject { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_ConfigManager_get") - func bjs_ConfigManager_get(_ self: Int32, _ key: Int32) -> Int32 - #else - func bjs_ConfigManager_get(_ self: Int32, _ key: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - var key = key - let keyId = key.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_ConfigManager_get(Int32(bitPattern: self.this.id), keyId) - if let error = _swift_js_take_exception() { - throw error - } - return JSObject(id: UInt32(bitPattern: ret)) - } - - func set(_ key: String, _ value: JSObject) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_ConfigManager_set") - func bjs_ConfigManager_set(_ self: Int32, _ key: Int32, _ value: Int32) -> Void - #else - func bjs_ConfigManager_set(_ self: Int32, _ key: Int32, _ value: Int32) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - var key = key - let keyId = key.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_ConfigManager_set(Int32(bitPattern: self.this.id), keyId, Int32(bitPattern: value.id)) - if let error = _swift_js_take_exception() { - throw error - } - } - -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/PrimitiveParameters.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/PrimitiveParameters.swift deleted file mode 100644 index c47f5f40e..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/PrimitiveParameters.swift +++ /dev/null @@ -1,22 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -func check(_ a: Double, _ b: Bool) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_check") - func bjs_check(_ a: Float64, _ b: Int32) -> Void - #else - func bjs_check(_ a: Float64, _ b: Int32) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - bjs_check(a, Int32(b ? 1 : 0)) - if let error = _swift_js_take_exception() { - throw error - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/PrimitiveReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/PrimitiveReturn.swift deleted file mode 100644 index cf26a52fa..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/PrimitiveReturn.swift +++ /dev/null @@ -1,39 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -func checkNumber() throws(JSException) -> Double { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_checkNumber") - func bjs_checkNumber() -> Float64 - #else - func bjs_checkNumber() -> Float64 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_checkNumber() - if let error = _swift_js_take_exception() { - throw error - } - return Double(ret) -} - -func checkBoolean() throws(JSException) -> Bool { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_checkBoolean") - func bjs_checkBoolean() -> Int32 - #else - func bjs_checkBoolean() -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_checkBoolean() - if let error = _swift_js_take_exception() { - throw error - } - return ret == 1 -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/StringParameter.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/StringParameter.swift deleted file mode 100644 index aabffacc4..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/StringParameter.swift +++ /dev/null @@ -1,45 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -func checkString(_ a: String) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_checkString") - func bjs_checkString(_ a: Int32) -> Void - #else - func bjs_checkString(_ a: Int32) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - var a = a - let aId = a.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_checkString(aId) - if let error = _swift_js_take_exception() { - throw error - } -} - -func checkStringWithLength(_ a: String, _ b: Double) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_checkStringWithLength") - func bjs_checkStringWithLength(_ a: Int32, _ b: Float64) -> Void - #else - func bjs_checkStringWithLength(_ a: Int32, _ b: Float64) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - var a = a - let aId = a.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_checkStringWithLength(aId, b) - if let error = _swift_js_take_exception() { - throw error - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/StringReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/StringReturn.swift deleted file mode 100644 index af7b51623..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/StringReturn.swift +++ /dev/null @@ -1,26 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -func checkString() throws(JSException) -> String { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_checkString") - func bjs_checkString() -> Int32 - #else - func bjs_checkString() -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_checkString() - if let error = _swift_js_take_exception() { - throw error - } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TS2SkeletonLike.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TS2SkeletonLike.swift deleted file mode 100644 index 95e9da8cc..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TS2SkeletonLike.swift +++ /dev/null @@ -1,173 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -func createTS2Skeleton() throws(JSException) -> TypeScriptProcessor { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_createTS2Skeleton") - func bjs_createTS2Skeleton() -> Int32 - #else - func bjs_createTS2Skeleton() -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_createTS2Skeleton() - if let error = _swift_js_take_exception() { - throw error - } - return TypeScriptProcessor(takingThis: ret) -} - -func createCodeGenerator(_ format: String) throws(JSException) -> CodeGenerator { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_createCodeGenerator") - func bjs_createCodeGenerator(_ format: Int32) -> Int32 - #else - func bjs_createCodeGenerator(_ format: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - var format = format - let formatId = format.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_createCodeGenerator(formatId) - if let error = _swift_js_take_exception() { - throw error - } - return CodeGenerator(takingThis: ret) -} - -struct TypeScriptProcessor { - let this: JSObject - - init(this: JSObject) { - self.this = this - } - - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) - } - - var version: String { - get throws(JSException) { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_TypeScriptProcessor_version_get") - func bjs_TypeScriptProcessor_version_get(_ self: Int32) -> Int32 - #else - func bjs_TypeScriptProcessor_version_get(_ self: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_TypeScriptProcessor_version_get(Int32(bitPattern: self.this.id)) - if let error = _swift_js_take_exception() { - throw error - } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } - } - } - - func convert(_ ts: String) throws(JSException) -> String { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_TypeScriptProcessor_convert") - func bjs_TypeScriptProcessor_convert(_ self: Int32, _ ts: Int32) -> Int32 - #else - func bjs_TypeScriptProcessor_convert(_ self: Int32, _ ts: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - var ts = ts - let tsId = ts.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_TypeScriptProcessor_convert(Int32(bitPattern: self.this.id), tsId) - if let error = _swift_js_take_exception() { - throw error - } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } - } - - func validate(_ ts: String) throws(JSException) -> Bool { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_TypeScriptProcessor_validate") - func bjs_TypeScriptProcessor_validate(_ self: Int32, _ ts: Int32) -> Int32 - #else - func bjs_TypeScriptProcessor_validate(_ self: Int32, _ ts: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - var ts = ts - let tsId = ts.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_TypeScriptProcessor_validate(Int32(bitPattern: self.this.id), tsId) - if let error = _swift_js_take_exception() { - throw error - } - return ret == 1 - } - -} - -struct CodeGenerator { - let this: JSObject - - init(this: JSObject) { - self.this = this - } - - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) - } - - var outputFormat: String { - get throws(JSException) { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_CodeGenerator_outputFormat_get") - func bjs_CodeGenerator_outputFormat_get(_ self: Int32) -> Int32 - #else - func bjs_CodeGenerator_outputFormat_get(_ self: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_CodeGenerator_outputFormat_get(Int32(bitPattern: self.this.id)) - if let error = _swift_js_take_exception() { - throw error - } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } - } - } - - func generate(_ input: JSObject) throws(JSException) -> String { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_CodeGenerator_generate") - func bjs_CodeGenerator_generate(_ self: Int32, _ input: Int32) -> Int32 - #else - func bjs_CodeGenerator_generate(_ self: Int32, _ input: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_CodeGenerator_generate(Int32(bitPattern: self.this.id), Int32(bitPattern: input.id)) - if let error = _swift_js_take_exception() { - throw error - } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } - } - -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TypeAlias.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TypeAlias.swift deleted file mode 100644 index 7523101fd..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TypeAlias.swift +++ /dev/null @@ -1,22 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -func checkSimple(_ a: Double) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_checkSimple") - func bjs_checkSimple(_ a: Float64) -> Void - #else - func bjs_checkSimple(_ a: Float64) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - bjs_checkSimple(a) - if let error = _swift_js_take_exception() { - throw error - } -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TypeScriptClass.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TypeScriptClass.swift deleted file mode 100644 index 7a1f2a2cd..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/TypeScriptClass.swift +++ /dev/null @@ -1,136 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -struct Greeter { - let this: JSObject - - init(this: JSObject) { - self.this = this - } - - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) - } - - init(_ name: String) throws(JSException) { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_Greeter_init") - func bjs_Greeter_init(_ name: Int32) -> Int32 - #else - func bjs_Greeter_init(_ name: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - var name = name - let nameId = name.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_Greeter_init(nameId) - if let error = _swift_js_take_exception() { - throw error - } - self.this = JSObject(id: UInt32(bitPattern: ret)) - } - - var name: String { - get throws(JSException) { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_Greeter_name_get") - func bjs_Greeter_name_get(_ self: Int32) -> Int32 - #else - func bjs_Greeter_name_get(_ self: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_Greeter_name_get(Int32(bitPattern: self.this.id)) - if let error = _swift_js_take_exception() { - throw error - } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } - } - } - - func setName(_ newValue: String) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_Greeter_name_set") - func bjs_Greeter_name_set(_ self: Int32, _ newValue: Int32) -> Void - #else - func bjs_Greeter_name_set(_ self: Int32, _ newValue: Int32) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - var newValue = newValue - let newValueId = newValue.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_Greeter_name_set(Int32(bitPattern: self.this.id), newValueId) - if let error = _swift_js_take_exception() { - throw error - } - } - - var age: Double { - get throws(JSException) { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_Greeter_age_get") - func bjs_Greeter_age_get(_ self: Int32) -> Float64 - #else - func bjs_Greeter_age_get(_ self: Int32) -> Float64 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_Greeter_age_get(Int32(bitPattern: self.this.id)) - if let error = _swift_js_take_exception() { - throw error - } - return Double(ret) - } - } - - func greet() throws(JSException) -> String { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_Greeter_greet") - func bjs_Greeter_greet(_ self: Int32) -> Int32 - #else - func bjs_Greeter_greet(_ self: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_Greeter_greet(Int32(bitPattern: self.this.id)) - if let error = _swift_js_take_exception() { - throw error - } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } - } - - func changeName(_ name: String) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_Greeter_changeName") - func bjs_Greeter_changeName(_ self: Int32, _ name: Int32) -> Void - #else - func bjs_Greeter_changeName(_ self: Int32, _ name: Int32) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - var name = name - let nameId = name.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_Greeter_changeName(Int32(bitPattern: self.this.id), nameId) - if let error = _swift_js_take_exception() { - throw error - } - } - -} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/VoidParameterVoidReturn.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/VoidParameterVoidReturn.swift deleted file mode 100644 index ae7ae0e8e..000000000 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/VoidParameterVoidReturn.swift +++ /dev/null @@ -1,22 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -func check() throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "Check", name: "bjs_check") - func bjs_check() -> Void - #else - func bjs_check() -> Void { - fatalError("Only available on WebAssembly") - } - #endif - bjs_check() - if let error = _swift_js_take_exception() { - throw error - } -} \ No newline at end of file diff --git a/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/README.md b/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/README.md new file mode 100644 index 000000000..3266c0c3d --- /dev/null +++ b/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/README.md @@ -0,0 +1,156 @@ +# Playwright OnPageLoad Test + +This example demonstrates how to expose JavaScript functions to your Swift/WebAssembly tests using Playwright's `page.exposeFunction` API. + +## How it works + +1. **Expose Script**: A JavaScript file that exports functions to be exposed in the browser context +2. **Swift Tests**: Call these exposed functions using JavaScriptKit's `JSObject.global` API +3. **Test Runner**: The `--playwright-expose` flag loads the script and exposes the functions before running tests + +## Usage + +### Define exposed functions in a JavaScript file + +**Important:** All functions exposed via Playwright's `page.exposeFunction` are async from the browser's perspective, meaning they always return Promises. Define them as `async` for clarity. + +#### Option 1: Function with Page Access (Recommended) + +Export a function that receives the Playwright `page` object. This allows your exposed functions to interact with the browser page: + +```javascript +/** + * @param {import('playwright').Page} page - The Playwright Page object + */ +export async function exposedFunctions(page) { + return { + expectToBeTrue: async () => { + return true; + }, + + // Use the page object to interact with the browser + getTitle: async () => { + return await page.title(); + }, + + clickButton: async (selector) => { + await page.click(selector); + return true; + }, + + evaluate: async (script) => { + return await page.evaluate(script); + }, + + screenshot: async () => { + const buffer = await page.screenshot(); + return buffer.toString('base64'); + } + }; +} +``` + +#### Option 2: Static Object (Simple Cases) + +For simple functions that don't need page access: + +```javascript +export const exposedFunctions = { + expectToBeTrue: async () => { + return true; + }, + + addNumbers: async (a, b) => { + return a + b; + } +}; +``` + +### Use the functions in Swift tests + +```swift +import XCTest +import JavaScriptKit +import JavaScriptEventLoop + +final class CheckTests: XCTestCase { + func testExpectToBeTrue() async throws { + guard let expectToBeTrue = JSObject.global.expectToBeTrue.function + else { return XCTFail("Function expectToBeTrue not found") } + + // Functions exposed via Playwright return Promises + guard let promiseObject = expectToBeTrue().object + else { return XCTFail("expectToBeTrue() did not return an object") } + + guard let promise = JSPromise(promiseObject) + else { return XCTFail("expectToBeTrue() did not return a Promise") } + + let resultValue = try await promise.value + guard let result = resultValue.boolean + else { return XCTFail("expectToBeTrue() returned nil") } + + XCTAssertTrue(result) + } +} +``` + +### Run tests with the expose script + +```bash +swift package js test --environment browser --playwright-expose path/to/expose.js +``` + +### Backward Compatibility + +You can also use `--prelude` to define exposed functions, which allows combining WASM setup options (`setupOptions`) and Playwright exposed functions in one file: + +```bash +swift package js test --environment browser --prelude path/to/prelude.js +``` + +However, using `--playwright-expose` is recommended for clarity and separation of concerns. + +## Advanced Usage + +### Access to Page Context + +When you export a function (as shown in Option 1), you receive the Playwright `page` object, which gives you full access to the browser page. This is powerful because you can: + +- **Query the DOM**: `await page.$('selector')` +- **Execute JavaScript**: `await page.evaluate('...')` +- **Take screenshots**: `await page.screenshot()` +- **Navigate**: `await page.goto('...')` +- **Handle events**: `page.on('console', ...)` + +### Async Initialization + +You can perform async initialization before returning your functions: + +```javascript +export async function exposedFunctions(page) { + // Perform async setup + const config = await loadConfiguration(); + + // Navigate to a specific page if needed + await page.goto('http://example.com'); + + return { + expectToBeTrue: async () => true, + + getConfig: async () => config, + + // Function that uses both page and initialization data + checkElement: async (selector) => { + const element = await page.$(selector); + return element !== null; + } + }; +} +``` + +### Best Practices + +1. **Always use `async` functions**: All exposed functions are async from the browser's perspective +2. **Capture `page` in closures**: Functions returned from `exposedFunctions(page)` can access `page` via closure +3. **Handle errors**: Wrap page interactions in try-catch blocks +4. **Return serializable data**: Functions can only return JSON-serializable values diff --git a/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/SwiftTesting/Package.swift b/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/SwiftTesting/Package.swift new file mode 100644 index 000000000..84130401a --- /dev/null +++ b/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/SwiftTesting/Package.swift @@ -0,0 +1,17 @@ +// swift-tools-version: 6.0 +import PackageDescription + +let package = Package( + name: "Check", + dependencies: [.package(name: "JavaScriptKit", path: "../../../../../")], + targets: [ + .testTarget( + name: "CheckTests", + dependencies: [ + "JavaScriptKit", + .product(name: "JavaScriptEventLoopTestSupport", package: "JavaScriptKit"), + ], + path: "Tests" + ) + ] +) diff --git a/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/SwiftTesting/Tests/CheckTests.swift b/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/SwiftTesting/Tests/CheckTests.swift new file mode 100644 index 000000000..e9b2f935c --- /dev/null +++ b/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/SwiftTesting/Tests/CheckTests.swift @@ -0,0 +1,25 @@ +import Testing +import JavaScriptKit +import JavaScriptEventLoop + +@Test func expectToBeTrue() async throws { + let expectToBeTrue = try #require(JSObject.global.expectToBeTrue.function) + + // expectToBeTrue returns a Promise, so we need to await it + let promiseObject = try #require(expectToBeTrue.callAsFunction().object) + let promise = try #require(JSPromise(promiseObject)) + + let resultValue = try await promise.value + #expect(resultValue.boolean == true) +} + +@Test func getTitleOfPage() async throws { + let getTitle = try #require(JSObject.global.getTitle.function) + + // getTitle returns a Promise, so we need to await it + let promiseObject = try #require(getTitle.callAsFunction().object) + let promise = try #require(JSPromise(promiseObject)) + + let resultValue = try await promise.value + #expect(resultValue.string == "") +} diff --git a/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/XCTest/Package.swift b/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/XCTest/Package.swift new file mode 100644 index 000000000..84130401a --- /dev/null +++ b/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/XCTest/Package.swift @@ -0,0 +1,17 @@ +// swift-tools-version: 6.0 +import PackageDescription + +let package = Package( + name: "Check", + dependencies: [.package(name: "JavaScriptKit", path: "../../../../../")], + targets: [ + .testTarget( + name: "CheckTests", + dependencies: [ + "JavaScriptKit", + .product(name: "JavaScriptEventLoopTestSupport", package: "JavaScriptKit"), + ], + path: "Tests" + ) + ] +) diff --git a/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/XCTest/Tests/CheckTests.swift b/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/XCTest/Tests/CheckTests.swift new file mode 100644 index 000000000..49d0a741e --- /dev/null +++ b/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/XCTest/Tests/CheckTests.swift @@ -0,0 +1,41 @@ +import XCTest +import JavaScriptKit +import JavaScriptEventLoop + +final class CheckTests: XCTestCase { + func testExpectToBeTrue() async throws { + guard let expectToBeTrue = JSObject.global.expectToBeTrue.function + else { return XCTFail("Function expectToBeTrue not found") } + + // expectToBeTrue returns a Promise, so we need to await it + guard let promiseObject = expectToBeTrue().object + else { return XCTFail("expectToBeTrue() did not return an object") } + + guard let promise = JSPromise(promiseObject) + else { return XCTFail("expectToBeTrue() did not return a Promise") } + + let resultValue = try await promise.value + guard let result = resultValue.boolean + else { return XCTFail("expectToBeTrue() returned nil") } + + XCTAssertTrue(result) + } + + func testTileOfPage() async throws { + guard let getTitle = JSObject.global.getTitle.function + else { return XCTFail("Function getTitle not found") } + + // getTitle returns a Promise, so we need to await it + guard let promiseObject = getTitle().object + else { return XCTFail("getTitle() did not return an object") } + + guard let promise = JSPromise(promiseObject) + else { return XCTFail("expectToBeTrue() did not return a Promise") } + + let resultValue = try await promise.value + guard let title = resultValue.string + else { return XCTFail("expectToBeTrue() returned nil") } + + XCTAssertTrue(title == "") + } +} diff --git a/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/expose.js b/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/expose.js new file mode 100644 index 000000000..22f760a14 --- /dev/null +++ b/Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/expose.js @@ -0,0 +1,49 @@ +/** + * Playwright exposed functions for PlaywrightOnPageLoadTest + * These functions will be exposed to the browser context and available as global functions + * in the WASM environment (accessible via JSObject.global) + * + * IMPORTANT: All exposed functions are async from the browser's perspective. + * Playwright's page.exposeFunction automatically wraps them to return Promises. + * Therefore, you must use JSPromise to await them in Swift. + */ + +/** + * Export a function that receives the Playwright Page object and returns the exposed functions. + * This allows your functions to interact with the page (click, query DOM, etc.) + * + * @param {import('playwright').Page} page - The Playwright Page object + * @returns {Object} An object mapping function names to async functions + */ +export async function exposedFunctions(page) { + return { + expectToBeTrue: async () => { + return true; + }, + + getTitle: async () => { + return await page.title(); + }, + + // clickButton: async (selector) => { + // await page.click(selector); + // return true; + // }, + + // screenshot: async () => { + // const buffer = await page.screenshot(); + // return buffer.toString('base64'); + // } + }; +} + +/** + * Alternative: Export a static object if you don't need page access + * (Note: This approach doesn't have access to the page object) + */ +// export const exposedFunctions = { +// expectToBeTrue: async () => { +// return true; +// }, +// addNumbers: async (a, b) => a + b, +// }; diff --git a/Plugins/PackageToJS/Package.swift b/Plugins/PackageToJS/Package.swift index 57ccf3cf9..fc3faa81c 100644 --- a/Plugins/PackageToJS/Package.swift +++ b/Plugins/PackageToJS/Package.swift @@ -10,7 +10,7 @@ let package = Package( .testTarget( name: "PackageToJSTests", dependencies: ["PackageToJS"], - exclude: ["__Snapshots__"] + exclude: ["__Snapshots__", "Inputs"] ), ] ) diff --git a/Plugins/PackageToJS/README.md b/Plugins/PackageToJS/README.md index 8b1821187..cbcaf19c5 100644 --- a/Plugins/PackageToJS/README.md +++ b/Plugins/PackageToJS/README.md @@ -41,5 +41,5 @@ swift test --package-path ./Plugins/PackageToJS Please define the following environment variables when you want to run E2E tests: - `SWIFT_SDK_ID`: Specifies the Swift SDK identifier to use -- `SWIFT_PATH`: Specifies the `bin` path to the Swift toolchain to use +- `SWIFT_BIN_PATH`: Specifies the `bin` path to the Swift toolchain to use diff --git a/Plugins/PackageToJS/Sources/BridgeJSUtilities b/Plugins/PackageToJS/Sources/BridgeJSUtilities new file mode 120000 index 000000000..52bf489db --- /dev/null +++ b/Plugins/PackageToJS/Sources/BridgeJSUtilities @@ -0,0 +1 @@ +../../../Plugins/BridgeJS/Sources/BridgeJSUtilities \ No newline at end of file diff --git a/Plugins/PackageToJS/Sources/MiniMake.swift b/Plugins/PackageToJS/Sources/MiniMake.swift index 0004af6c0..663635b7c 100644 --- a/Plugins/PackageToJS/Sources/MiniMake.swift +++ b/Plugins/PackageToJS/Sources/MiniMake.swift @@ -93,14 +93,18 @@ struct MiniMake { private var tasks: [TaskKey: Task] /// Whether to explain why tasks are built private var shouldExplain: Bool + /// File system operations + private var fileSystem: MiniMakeFileSystem /// Prints progress of the build private var printProgress: ProgressPrinter.PrintProgress init( explain: Bool = false, + fileSystem: MiniMakeFileSystem = DefaultMiniMakeFileSystem(), printProgress: @escaping ProgressPrinter.PrintProgress ) { self.tasks = [:] + self.fileSystem = fileSystem self.shouldExplain = explain self.printProgress = printProgress } @@ -222,7 +226,7 @@ struct MiniMake { /// Cleans all outputs of all tasks func cleanEverything(scope: VariableScope) { for task in self.tasks.values { - try? FileManager.default.removeItem(at: scope.resolve(path: task.output)) + try? fileSystem.removeItem(at: scope.resolve(path: task.output)) } } @@ -234,26 +238,20 @@ struct MiniMake { return true } let outputURL = scope.resolve(path: task.output) - if !FileManager.default.fileExists(atPath: outputURL.path) { + if !fileSystem.fileExists(at: outputURL) { explain("Task \(task.output) should be built because it doesn't exist") return true } - let outputMtime = try? outputURL.resourceValues(forKeys: [.contentModificationDateKey]) - .contentModificationDate + let outputMtime = try? fileSystem.modificationDate(of: outputURL) return task.inputs.contains { input in let inputURL = scope.resolve(path: input) // Ignore directory modification times - var isDirectory: ObjCBool = false - let fileExists = FileManager.default.fileExists( - atPath: inputURL.path, - isDirectory: &isDirectory - ) - if fileExists && isDirectory.boolValue { + let (fileExists, isDirectory) = fileSystem.fileExists(at: inputURL) + if fileExists && isDirectory { return false } - let inputMtime = try? inputURL.resourceValues(forKeys: [.contentModificationDateKey] - ).contentModificationDate + let inputMtime = try? fileSystem.modificationDate(of: inputURL) let shouldBuild = outputMtime == nil || inputMtime == nil || outputMtime! < inputMtime! if shouldBuild { @@ -337,3 +335,32 @@ struct BuildPath: Encodable, Hashable, CustomStringConvertible { try container.encode(self.description) } } + +/// Abstraction over file system operations +protocol MiniMakeFileSystem { + func removeItem(at url: URL) throws + func fileExists(at url: URL) -> Bool + func fileExists(at url: URL) -> (exists: Bool, isDirectory: Bool) + func modificationDate(of url: URL) throws -> Date? +} + +/// Default implementation of MiniMakeFileSystem using FileManager +struct DefaultMiniMakeFileSystem: MiniMakeFileSystem { + func removeItem(at url: URL) throws { + try FileManager.default.removeItem(at: url) + } + + func fileExists(at url: URL) -> Bool { + FileManager.default.fileExists(atPath: url.path) + } + + func fileExists(at url: URL) -> (exists: Bool, isDirectory: Bool) { + var isDirectory: ObjCBool = false + let exists = FileManager.default.fileExists(atPath: url.path, isDirectory: &isDirectory) + return (exists, isDirectory.boolValue) + } + + func modificationDate(of url: URL) throws -> Date? { + try url.resourceValues(forKeys: [.contentModificationDateKey]).contentModificationDate + } +} diff --git a/Plugins/PackageToJS/Sources/PackageToJS.swift b/Plugins/PackageToJS/Sources/PackageToJS.swift index c486c327a..3e22736be 100644 --- a/Plugins/PackageToJS/Sources/PackageToJS.swift +++ b/Plugins/PackageToJS/Sources/PackageToJS.swift @@ -2,12 +2,19 @@ import Foundation struct PackageToJS { struct PackageOptions { + enum Platform: String, CaseIterable { + case browser + case node + } + /// Path to the output directory var outputPath: String? /// The build configuration to use (default: debug) var configuration: String? /// Name of the package (default: lowercased Package.swift name) var packageName: String? + /// Target platform for the generated JavaScript (default: browser) + var defaultPlatform: Platform = .browser /// Whether to explain the build plan (default: false) var explain: Bool = false /// Whether to print verbose output @@ -51,6 +58,8 @@ struct PackageToJS { var environment: String? /// Whether to run tests in the browser with inspector enabled var inspect: Bool + /// The script defining Playwright exposed functions + var playwrightExpose: String? /// The extra arguments to pass to node var extraNodeArguments: [String] /// The options for packaging @@ -82,6 +91,14 @@ struct PackageToJS { testJsArguments.append("--prelude") testJsArguments.append(preludeURL.path) } + if let playwrightExpose = testOptions.playwrightExpose { + let playwrightExposeURL = URL( + fileURLWithPath: playwrightExpose, + relativeTo: URL(fileURLWithPath: FileManager.default.currentDirectoryPath) + ) + testJsArguments.append("--playwright-expose") + testJsArguments.append(playwrightExposeURL.path) + } if let environment = testOptions.environment { testJsArguments.append("--environment") testJsArguments.append(environment) @@ -377,10 +394,8 @@ struct PackagingPlanner { let selfPackageDir: BuildPath /// The path of this file itself, used to capture changes of planner code let selfPath: BuildPath - /// The exported API skeletons source files - let exportedSkeletons: [BuildPath] - /// The imported API skeletons source files - let importedSkeletons: [BuildPath] + /// The BridgeJS API skeletons source files + let skeletons: [BuildPath] /// The directory for the final output let outputDir: BuildPath /// The directory for intermediate files @@ -401,21 +416,22 @@ struct PackagingPlanner { packageId: String, intermediatesDir: BuildPath, selfPackageDir: BuildPath, - exportedSkeletons: [BuildPath], - importedSkeletons: [BuildPath], + skeletons: [BuildPath], outputDir: BuildPath, wasmProductArtifact: BuildPath, wasmFilename: String, configuration: String, triple: String, - selfPath: BuildPath = BuildPath(absolute: #filePath), + // NOTE: We should use `ProcessInfo.processInfo.arguments[0]` instead of `CommandLine.arguments[0]` + // because the latter may not always be the full executable path (e.g. when invoked through PATH lookup). + // https://github.com/swiftlang/swift-foundation/blob/f5143f96d01cdb6d280665de8221b75fc8631d95/Sources/FoundationEssentials/ProcessInfo/ProcessInfo.swift#L47 + selfPath: BuildPath = BuildPath(absolute: ProcessInfo.processInfo.arguments[0]), system: any PackagingSystem ) { self.options = options self.packageId = packageId self.selfPackageDir = selfPackageDir - self.exportedSkeletons = exportedSkeletons - self.importedSkeletons = importedSkeletons + self.skeletons = skeletons self.outputDir = outputDir self.intermediatesDir = intermediatesDir self.wasmFilename = wasmFilename @@ -575,29 +591,21 @@ struct PackagingPlanner { ) packageInputs.append(packageJsonTask) - if exportedSkeletons.count > 0 || importedSkeletons.count > 0 { - if ProcessInfo.processInfo.environment["JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS"] == nil { - fatalError( - "BridgeJS is still an experimental feature. Set the environment variable JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 to enable." - ) - } + if skeletons.count > 0 { let bridgeJs = outputDir.appending(path: "bridge-js.js") let bridgeDts = outputDir.appending(path: "bridge-js.d.ts") packageInputs.append( - make.addTask(inputFiles: exportedSkeletons + importedSkeletons, output: bridgeJs) { _, scope in - let link = try BridgeJSLink( - exportedSkeletons: exportedSkeletons.map { - let decoder = JSONDecoder() - let data = try Data(contentsOf: URL(fileURLWithPath: scope.resolve(path: $0).path)) - return try decoder.decode(ExportedSkeleton.self, from: data) - }, - importedSkeletons: importedSkeletons.map { - let decoder = JSONDecoder() - let data = try Data(contentsOf: URL(fileURLWithPath: scope.resolve(path: $0).path)) - return try decoder.decode(ImportedModuleSkeleton.self, from: data) - }, + make.addTask(inputFiles: skeletons + [selfPath], output: bridgeJs) { _, scope in + var link = BridgeJSLink( sharedMemory: Self.isSharedMemoryEnabled(triple: triple) ) + + // Decode skeleton format + for skeletonPath in skeletons { + let data = try Data(contentsOf: URL(fileURLWithPath: scope.resolve(path: skeletonPath).path)) + try link.addSkeletonFile(data: data) + } + let (outputJs, outputDts) = try link.link() try system.writeFile(atPath: scope.resolve(path: bridgeJs).path, content: Data(outputJs.utf8)) try system.writeFile(atPath: scope.resolve(path: bridgeDts).path, content: Data(outputDts.utf8)) @@ -715,8 +723,10 @@ struct PackagingPlanner { "USE_SHARED_MEMORY": Self.isSharedMemoryEnabled(triple: triple), "IS_WASI": triple.hasPrefix("wasm32-unknown-wasi"), "USE_WASI_CDN": options.useCDN, - "HAS_BRIDGE": exportedSkeletons.count > 0 || importedSkeletons.count > 0, - "HAS_IMPORTS": importedSkeletons.count > 0, + "HAS_BRIDGE": skeletons.count > 0, + "HAS_IMPORTS": skeletons.count > 0, + "TARGET_DEFAULT_PLATFORM_NODE": options.defaultPlatform == .node, + "TARGET_DEFAULT_PLATFORM_BROWSER": options.defaultPlatform == .browser, ] let constantSubstitutions: [String: String] = [ "PACKAGE_TO_JS_MODULE_PATH": wasmFilename, diff --git a/Plugins/PackageToJS/Sources/PackageToJSPlugin.swift b/Plugins/PackageToJS/Sources/PackageToJSPlugin.swift index 75c736754..7e335c68e 100644 --- a/Plugins/PackageToJS/Sources/PackageToJSPlugin.swift +++ b/Plugins/PackageToJS/Sources/PackageToJSPlugin.swift @@ -166,7 +166,7 @@ struct PackageToJSPlugin: CommandPlugin { } } - static let JAVASCRIPTKIT_PACKAGE_ID: Package.ID = "javascriptkit" + static let JAVASCRIPTEVENTLOOP_PRODUCT_ID: Product.ID = "JavaScriptEventLoop" func performBuildCommand(context: PluginContext, arguments: [String]) throws { if arguments.contains(where: { ["-h", "--help"].contains($0) }) { @@ -175,7 +175,7 @@ struct PackageToJSPlugin: CommandPlugin { } var extractor = ArgumentExtractor(arguments) - let buildOptions = PackageToJS.BuildOptions.parse(from: &extractor) + let buildOptions = try PackageToJS.BuildOptions.parse(from: &extractor) if extractor.remainingArguments.count > 0 { printStderr( @@ -199,7 +199,7 @@ struct PackageToJSPlugin: CommandPlugin { exit(1) } let skeletonCollector = SkeletonCollector(context: context) - let (exportedSkeletons, importedSkeletons) = skeletonCollector.collectFromProduct(name: productName) + let skeletons = skeletonCollector.collectFromProduct(name: productName) let productArtifact = try build.findWasmArtifact(for: productName) let outputDir = if let outputPath = buildOptions.packageOptions.outputPath { @@ -215,8 +215,7 @@ struct PackageToJSPlugin: CommandPlugin { options: buildOptions.packageOptions, context: context, selfPackage: selfPackage, - exportedSkeletons: exportedSkeletons, - importedSkeletons: importedSkeletons, + skeletons: skeletons, outputDir: outputDir, wasmProductArtifact: productArtifact, wasmFilename: productArtifact.lastPathComponent @@ -239,7 +238,7 @@ struct PackageToJSPlugin: CommandPlugin { } var extractor = ArgumentExtractor(arguments) - let testOptions = PackageToJS.TestOptions.parse(from: &extractor) + let testOptions = try PackageToJS.TestOptions.parse(from: &extractor) if extractor.remainingArguments.count > 0 { printStderr( @@ -263,7 +262,7 @@ struct PackageToJSPlugin: CommandPlugin { } let skeletonCollector = SkeletonCollector(context: context) - let (exportedSkeletons, importedSkeletons) = skeletonCollector.collectFromTests() + let skeletons = skeletonCollector.collectFromTests() // NOTE: Find the product artifact from the default build directory // because PackageManager.BuildResult doesn't include the @@ -300,8 +299,7 @@ struct PackageToJSPlugin: CommandPlugin { options: testOptions.packageOptions, context: context, selfPackage: selfPackage, - exportedSkeletons: exportedSkeletons, - importedSkeletons: importedSkeletons, + skeletons: skeletons, outputDir: outputDir, wasmProductArtifact: productArtifact, // If the product artifact doesn't have a .wasm extension, add it @@ -396,7 +394,11 @@ struct PackageToJSPlugin: CommandPlugin { guard let selfPackage = findPackageInDependencies( package: package, - id: Self.JAVASCRIPTKIT_PACKAGE_ID + // NOTE: We use JavaScriptEventLoop product to find the JavaScriptKit package + // instead of JavaScriptKit product because SwiftPM in 6.0 does not returns + // product information for JavaScriptKit product for some reason (very likely + // a bug in SwiftPM). + including: Self.JAVASCRIPTEVENTLOOP_PRODUCT_ID ) else { throw PackageToJSError("Failed to find JavaScriptKit in dependencies!?") @@ -440,12 +442,28 @@ private func printStderr(_ message: String) { // MARK: - Options parsing +extension ArgumentExtractor { + mutating func extractPlatformOption(named name: String) throws -> PackageToJS.PackageOptions.Platform { + guard let stringValue = self.extractOption(named: name).last else { + return .browser + } + + guard let platform = PackageToJS.PackageOptions.Platform(rawValue: stringValue) else { + throw PackageToJSError( + "Invalid platform: \(stringValue), expected one of \(PackageToJS.PackageOptions.Platform.allCases.map(\.rawValue).joined(separator: ", "))" + ) + } + return platform + } +} + extension PackageToJS.PackageOptions { - static func parse(from extractor: inout ArgumentExtractor) -> PackageToJS.PackageOptions { + static func parse(from extractor: inout ArgumentExtractor) throws -> PackageToJS.PackageOptions { let outputPath = extractor.extractOption(named: "output").last let configuration: String? = (extractor.extractOption(named: "configuration") + extractor.extractSingleDashOption(named: "c")).last let packageName = extractor.extractOption(named: "package-name").last + let defaultPlatform = try extractor.extractPlatformOption(named: "default-platform") let explain = extractor.extractFlag(named: "explain") let useCDN = extractor.extractFlag(named: "use-cdn") let verbose = extractor.extractFlag(named: "verbose") @@ -454,6 +472,7 @@ extension PackageToJS.PackageOptions { outputPath: outputPath, configuration: configuration, packageName: packageName, + defaultPlatform: defaultPlatform, explain: explain != 0, verbose: verbose != 0, useCDN: useCDN != 0, @@ -466,6 +485,7 @@ extension PackageToJS.PackageOptions { --output Path to the output directory (default: .build/plugins/PackageToJS/outputs/Package) -c, --configuration The build configuration to use (values: debug, release; default: debug) --package-name Name of the package (default: lowercased Package.swift name) + --platform Target platform for generated JavaScript (values: \(PackageToJS.PackageOptions.Platform.allCases.map(\.rawValue).joined(separator: ", ")); default: \(PackageToJS.PackageOptions.Platform.browser)) --use-cdn Whether to use CDN for dependency packages --enable-code-coverage Whether to enable code coverage collection --explain Whether to explain the build plan @@ -475,7 +495,7 @@ extension PackageToJS.PackageOptions { } extension PackageToJS.BuildOptions { - static func parse(from extractor: inout ArgumentExtractor) -> PackageToJS.BuildOptions { + static func parse(from extractor: inout ArgumentExtractor) throws -> PackageToJS.BuildOptions { let product = extractor.extractOption(named: "product").last let noOptimize = extractor.extractFlag(named: "no-optimize") let rawDebugInfoFormat = extractor.extractOption(named: "debug-info-format").last @@ -488,7 +508,7 @@ extension PackageToJS.BuildOptions { } debugInfoFormat = format } - let packageOptions = PackageToJS.PackageOptions.parse(from: &extractor) + let packageOptions = try PackageToJS.PackageOptions.parse(from: &extractor) return PackageToJS.BuildOptions( product: product, noOptimize: noOptimize != 0, @@ -526,15 +546,16 @@ extension PackageToJS.BuildOptions { } extension PackageToJS.TestOptions { - static func parse(from extractor: inout ArgumentExtractor) -> PackageToJS.TestOptions { + static func parse(from extractor: inout ArgumentExtractor) throws -> PackageToJS.TestOptions { let buildOnly = extractor.extractFlag(named: "build-only") let listTests = extractor.extractFlag(named: "list-tests") let filter = extractor.extractOption(named: "filter") let prelude = extractor.extractOption(named: "prelude").last let environment = extractor.extractOption(named: "environment").last let inspect = extractor.extractFlag(named: "inspect") + let playwrightExpose = extractor.extractOption(named: "playwright-expose").last let extraNodeArguments = extractor.extractSingleDashOption(named: "Xnode") - let packageOptions = PackageToJS.PackageOptions.parse(from: &extractor) + let packageOptions = try PackageToJS.PackageOptions.parse(from: &extractor) var options = PackageToJS.TestOptions( buildOnly: buildOnly != 0, listTests: listTests != 0, @@ -542,6 +563,7 @@ extension PackageToJS.TestOptions { prelude: prelude, environment: environment, inspect: inspect != 0, + playwrightExpose: playwrightExpose, extraNodeArguments: extraNodeArguments, packageOptions: packageOptions ) @@ -564,6 +586,7 @@ extension PackageToJS.TestOptions { --prelude Path to the prelude script --environment The environment to use for the tests (values: node, browser; default: node) --inspect Whether to run tests in the browser with inspector enabled + --playwright-expose Path to script defining Playwright exposed functions -Xnode Extra arguments to pass to Node.js \(PackageToJS.PackageOptions.optionsHelp()) @@ -649,12 +672,24 @@ extension PackageManager.BuildResult { } } -private func findPackageInDependencies(package: Package, id: Package.ID) -> Package? { +/// Find the package that contains the product with the given name +/// - Parameters: +/// - package: The package to search in +/// - productName: The name of the product to find +/// - Returns: The package that contains the product with the given name +/// - Note: Why not use `Package.ID`? `Package.ID` is not always equal to the package repository name +/// as it's derived from the directory name when the package is dependent on another package as a +// local package. +private func findPackageInDependencies(package: Package, including productName: String) -> Package? { var visited: Set = [] func visit(package: Package) -> Package? { if visited.contains(package.id) { return nil } visited.insert(package.id) - if package.id == id { return package } + for product in package.products { + if product.name == productName { + return package + } + } for dependency in package.dependencies { if let found = visit(package: dependency.package) { return found @@ -669,25 +704,23 @@ class SkeletonCollector { private var visitedProducts: Set = [] private var visitedTargets: Set = [] - var exportedSkeletons: [URL] = [] - var importedSkeletons: [URL] = [] - let exportedSkeletonFile = "BridgeJS.ExportSwift.json" - let importedSkeletonFile = "BridgeJS.ImportTS.json" + var skeletons: [URL] = [] + let skeletonFile = "BridgeJS.json" let context: PluginContext init(context: PluginContext) { self.context = context } - func collectFromProduct(name: String) -> (exportedSkeletons: [URL], importedSkeletons: [URL]) { + func collectFromProduct(name: String) -> [URL] { guard let product = context.package.products.first(where: { $0.name == name }) else { - return ([], []) + return [] } visit(product: product, package: context.package) - return (exportedSkeletons, importedSkeletons) + return skeletons } - func collectFromTests() -> (exportedSkeletons: [URL], importedSkeletons: [URL]) { + func collectFromTests() -> [URL] { let tests = context.package.targets.filter { guard let target = $0 as? SwiftSourceModuleTarget else { return false } return target.kind == .test @@ -695,7 +728,7 @@ class SkeletonCollector { for test in tests { visit(target: test, package: context.package) } - return (exportedSkeletons, importedSkeletons) + return skeletons } private func visit(product: Product, package: Package) { @@ -709,22 +742,23 @@ class SkeletonCollector { private func visit(target: Target, package: Package) { if visitedTargets.contains(target.id) { return } visitedTargets.insert(target.id) + if let sourceModuleTarget = target as? SourceModuleTarget { + if sourceModuleTarget.kind == .macro { + return + } + } if let target = target as? SwiftSourceModuleTarget { let directories = [ target.directoryURL.appending(path: "Generated/JavaScript"), // context.pluginWorkDirectoryURL: ".build/plugins/PackageToJS/outputs/" - // .build/plugins/outputs/exportswift/MyApp/destination/BridgeJS/BridgeJS.ExportSwift.json + // .build/plugins/outputs/[package]/[target]/destination/BridgeJS/JavaScript/BridgeJS.json context.pluginWorkDirectoryURL.deletingLastPathComponent().deletingLastPathComponent() - .appending(path: "outputs/\(package.id)/\(target.name)/destination/BridgeJS"), + .appending(path: "outputs/\(package.id)/\(target.name)/destination/BridgeJS/JavaScript"), ] for directory in directories { - let exportedSkeletonURL = directory.appending(path: exportedSkeletonFile) - let importedSkeletonURL = directory.appending(path: importedSkeletonFile) - if FileManager.default.fileExists(atPath: exportedSkeletonURL.path) { - exportedSkeletons.append(exportedSkeletonURL) - } - if FileManager.default.fileExists(atPath: importedSkeletonURL.path) { - importedSkeletons.append(importedSkeletonURL) + let skeletonURL = directory.appending(path: skeletonFile) + if FileManager.default.fileExists(atPath: skeletonURL.path) { + skeletons.append(skeletonURL) } } } @@ -754,8 +788,7 @@ extension PackagingPlanner { options: PackageToJS.PackageOptions, context: PluginContext, selfPackage: Package, - exportedSkeletons: [URL], - importedSkeletons: [URL], + skeletons: [URL], outputDir: URL, wasmProductArtifact: URL, wasmFilename: String @@ -770,8 +803,7 @@ extension PackagingPlanner { absolute: context.pluginWorkDirectoryURL.appending(path: outputBaseName + ".tmp").path ), selfPackageDir: BuildPath(absolute: selfPackage.directoryURL.path), - exportedSkeletons: exportedSkeletons.map { BuildPath(absolute: $0.path) }, - importedSkeletons: importedSkeletons.map { BuildPath(absolute: $0.path) }, + skeletons: skeletons.map { BuildPath(absolute: $0.path) }, outputDir: BuildPath(absolute: outputDir.path), wasmProductArtifact: BuildPath(absolute: wasmProductArtifact.path), wasmFilename: wasmFilename, diff --git a/Plugins/PackageToJS/Templates/bin/test.js b/Plugins/PackageToJS/Templates/bin/test.js index e7444e901..82ef88cc2 100644 --- a/Plugins/PackageToJS/Templates/bin/test.js +++ b/Plugins/PackageToJS/Templates/bin/test.js @@ -33,6 +33,7 @@ const args = parseArgs({ environment: { type: "string" }, inspect: { type: "boolean" }, "coverage-file": { type: "string" }, + "playwright-expose": { type: "string" }, }, }) @@ -95,7 +96,47 @@ Hint: This typically means that a continuation leak occurred. } }, browser: async ({ preludeScript }) => { - process.exit(await testBrowser({ preludeScript, inspect: args.values.inspect, args: testFrameworkArgs })); + let onPageLoad = undefined; + + // Load exposed functions from playwright-expose flag + if (args.values["playwright-expose"]) { + const exposeScript = path.resolve(process.cwd(), args.values["playwright-expose"]); + try { + const exposeModule = await import(exposeScript); + const exposedFunctions = exposeModule.exposedFunctions; + + if (exposedFunctions) { + onPageLoad = async (page) => { + // If exposedFunctions is a function, call it with the page object + // This allows the functions to capture the page in their closure + const functions = typeof exposedFunctions === 'function' + ? await exposedFunctions(page) + : exposedFunctions; + + 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 + await page.exposeFunction(name, fn); + } + }; + } + } catch (e) { + // If --playwright-expose is specified but file doesn't exist or has no exposedFunctions, that's an error + if (args.values["playwright-expose"]) { + throw e; + } + } + } + + const exitCode = await testBrowser({ + preludeScript, + inspect: args.values.inspect, + args: testFrameworkArgs, + playwright: { + onPageLoad + } + }); + process.exit(exitCode); } } diff --git a/Plugins/PackageToJS/Templates/index.d.ts b/Plugins/PackageToJS/Templates/index.d.ts index 757a88287..fb063f0ab 100644 --- a/Plugins/PackageToJS/Templates/index.d.ts +++ b/Plugins/PackageToJS/Templates/index.d.ts @@ -1,12 +1,14 @@ import type { Exports, Imports, ModuleSource } from './instantiate.js' export type Options = { +/* #if TARGET_DEFAULT_PLATFORM_BROWSER */ /** * The WebAssembly module to instantiate * * If not provided, the module will be fetched from the default path. */ module?: ModuleSource +/* #endif */ /* #if HAS_IMPORTS */ /** * The imports to use for the module diff --git a/Plugins/PackageToJS/Templates/index.js b/Plugins/PackageToJS/Templates/index.js index f44dce480..7cde8edc9 100644 --- a/Plugins/PackageToJS/Templates/index.js +++ b/Plugins/PackageToJS/Templates/index.js @@ -1,9 +1,29 @@ // @ts-check import { instantiate } from './instantiate.js'; -import { defaultBrowserSetup /* #if USE_SHARED_MEMORY */, createDefaultWorkerFactory /* #endif */} from './platforms/browser.js'; +/* #if TARGET_DEFAULT_PLATFORM_NODE */ +import { defaultNodeSetup /* #if USE_SHARED_MEMORY */, createDefaultWorkerFactory as createDefaultWorkerFactoryForNode /* #endif */} from './platforms/node.js'; +/* #else */ +import { defaultBrowserSetup /* #if USE_SHARED_MEMORY */, createDefaultWorkerFactory as createDefaultWorkerFactoryForBrowser /* #endif */} from './platforms/browser.js'; +/* #endif */ +/* #if TARGET_DEFAULT_PLATFORM_NODE */ /** @type {import('./index.d').init} */ -export async function init(_options) { +async function initNode(_options) { + /** @type {import('./platforms/node.d.ts').DefaultNodeSetupOptions} */ + const options = { + ...(_options || {}), +/* #if USE_SHARED_MEMORY */ + spawnWorker: createDefaultWorkerFactoryForNode(), +/* #endif */ + }; + const instantiateOptions = await defaultNodeSetup(options); + return await instantiate(instantiateOptions); +} + +/* #else */ + +/** @type {import('./index.d').init} */ +async function initBrowser(_options) { /** @type {import('./index.d').Options} */ const options = _options || { /* #if HAS_IMPORTS */ @@ -21,8 +41,19 @@ export async function init(_options) { getImports: () => options.getImports(), /* #endif */ /* #if USE_SHARED_MEMORY */ - spawnWorker: createDefaultWorkerFactory() + spawnWorker: createDefaultWorkerFactoryForBrowser() /* #endif */ }) return await instantiate(instantiateOptions); } + +/* #endif */ + +/** @type {import('./index.d').init} */ +export async function init(options) { + /* #if TARGET_DEFAULT_PLATFORM_NODE */ + return initNode(options); + /* #else */ + return initBrowser(options); + /* #endif */ +} \ No newline at end of file diff --git a/Plugins/PackageToJS/Templates/instantiate.js b/Plugins/PackageToJS/Templates/instantiate.js index 5d6fe6b90..c9bc9efb4 100644 --- a/Plugins/PackageToJS/Templates/instantiate.js +++ b/Plugins/PackageToJS/Templates/instantiate.js @@ -4,17 +4,17 @@ import { SwiftRuntime } from "./runtime.js" export const MODULE_PATH = "@PACKAGE_TO_JS_MODULE_PATH@"; /* #if USE_SHARED_MEMORY */ export const MEMORY_TYPE = { - // @ts-ignore + // @ts-expect-error Substituted by PackageToJS preprocessor initial: import.meta.PACKAGE_TO_JS_MEMORY_INITIAL, - // @ts-ignore + // @ts-expect-error Substituted by PackageToJS preprocessor maximum: import.meta.PACKAGE_TO_JS_MEMORY_MAXIMUM, - // @ts-ignore + // @ts-expect-error Substituted by PackageToJS preprocessor shared: import.meta.PACKAGE_TO_JS_MEMORY_SHARED, } /* #endif */ /* #if HAS_BRIDGE */ -// @ts-ignore +// @ts-expect-error Substituted by PackageToJS preprocessor import { createInstantiator } from "./bridge-js.js" /* #else */ /** @@ -27,7 +27,46 @@ async function createInstantiator(options, swift) { * @param {WebAssembly.Imports} importObject * @param {unknown} importsContext */ - addImports: (importObject, importsContext) => {}, + addImports: (importObject, importsContext) => { + // Provide a default implementation for BridgeJS functions that are not + // used at runtime without BridgeJS but required to instantiate the module. + const unexpectedBjsCall = () => { throw new Error("Unexpected call to BridgeJS function") } + importObject["bjs"] = { + swift_js_return_string: unexpectedBjsCall, + swift_js_init_memory: unexpectedBjsCall, + swift_js_make_js_string: unexpectedBjsCall, + swift_js_init_memory_with_result: unexpectedBjsCall, + swift_js_throw: unexpectedBjsCall, + swift_js_retain: unexpectedBjsCall, + swift_js_release: unexpectedBjsCall, + swift_js_push_i32: unexpectedBjsCall, + swift_js_push_f32: unexpectedBjsCall, + swift_js_push_f64: unexpectedBjsCall, + swift_js_push_string: 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, + swift_js_return_optional_double: unexpectedBjsCall, + swift_js_return_optional_float: unexpectedBjsCall, + swift_js_return_optional_heap_object: unexpectedBjsCall, + swift_js_return_optional_object: unexpectedBjsCall, + swift_js_get_optional_int_presence: unexpectedBjsCall, + swift_js_get_optional_int_value: unexpectedBjsCall, + swift_js_get_optional_string: unexpectedBjsCall, + swift_js_get_optional_float_presence: unexpectedBjsCall, + swift_js_get_optional_float_value: unexpectedBjsCall, + swift_js_get_optional_double_presence: unexpectedBjsCall, + swift_js_get_optional_double_value: unexpectedBjsCall, + swift_js_get_optional_heap_object_pointer: unexpectedBjsCall, + swift_js_push_pointer: unexpectedBjsCall, + swift_js_pop_pointer: unexpectedBjsCall, + swift_js_struct_cleanup: unexpectedBjsCall, + swift_js_closure_unregister: unexpectedBjsCall, + } + }, /** @param {WebAssembly.Instance} instance */ setInstance: (instance) => {}, /** @param {WebAssembly.Instance} instance */ diff --git a/Plugins/PackageToJS/Templates/package.json b/Plugins/PackageToJS/Templates/package.json index a41e6db28..a3e7074bb 100644 --- a/Plugins/PackageToJS/Templates/package.json +++ b/Plugins/PackageToJS/Templates/package.json @@ -9,13 +9,5 @@ }, "dependencies": { "@bjorn3/browser_wasi_shim": "0.3.0" - }, - "peerDependencies": { - "playwright": "^1.51.0" - }, - "peerDependenciesMeta": { - "playwright": { - "optional": true - } } } diff --git a/Plugins/PackageToJS/Templates/platforms/browser.d.ts b/Plugins/PackageToJS/Templates/platforms/browser.d.ts index babe3f487..dcfb5f617 100644 --- a/Plugins/PackageToJS/Templates/platforms/browser.d.ts +++ b/Plugins/PackageToJS/Templates/platforms/browser.d.ts @@ -11,7 +11,7 @@ export function defaultBrowserSetup(options: { getImports: () => Imports, /* #endif */ /* #if USE_SHARED_MEMORY */ - spawnWorker: (module: WebAssembly.Module, memory: WebAssembly.Memory, startArg: any) => Worker, + spawnWorker?: (module: WebAssembly.Module, memory: WebAssembly.Memory, startArg: any) => Worker, /* #endif */ }): Promise diff --git a/Plugins/PackageToJS/Templates/platforms/browser.js b/Plugins/PackageToJS/Templates/platforms/browser.js index 3fce7c556..d471e8415 100644 --- a/Plugins/PackageToJS/Templates/platforms/browser.js +++ b/Plugins/PackageToJS/Templates/platforms/browser.js @@ -118,7 +118,7 @@ export async function defaultBrowserSetup(options) { /* #endif */ /* #if USE_SHARED_MEMORY */ const memory = new WebAssembly.Memory(MEMORY_TYPE); - const threadChannel = new DefaultBrowserThreadRegistry(options.spawnWorker) + const threadChannel = new DefaultBrowserThreadRegistry(options.spawnWorker || createDefaultWorkerFactory()) /* #endif */ return { diff --git a/Plugins/PackageToJS/Templates/platforms/node.d.ts b/Plugins/PackageToJS/Templates/platforms/node.d.ts index 9d80205fc..4b8d95843 100644 --- a/Plugins/PackageToJS/Templates/platforms/node.d.ts +++ b/Plugins/PackageToJS/Templates/platforms/node.d.ts @@ -1,14 +1,16 @@ import type { InstantiateOptions } from "../instantiate.js" import type { Worker } from "node:worker_threads" -export function defaultNodeSetup(options: { +export type DefaultNodeSetupOptions = { /* #if IS_WASI */ args?: string[], /* #endif */ onExit?: (code: number) => void, /* #if USE_SHARED_MEMORY */ - spawnWorker: (module: WebAssembly.Module, memory: WebAssembly.Memory, startArg: any) => Worker, + spawnWorker?: (module: WebAssembly.Module, memory: WebAssembly.Memory, startArg: any) => Worker, /* #endif */ -}): Promise +} -export function createDefaultWorkerFactory(preludeScript: string): (module: WebAssembly.Module, memory: WebAssembly.Memory, startArg: any) => Worker +export function defaultNodeSetup(options?: DefaultNodeSetupOptions): Promise + +export function createDefaultWorkerFactory(preludeScript?: string): (module: WebAssembly.Module, memory: WebAssembly.Memory, startArg: any) => Worker diff --git a/Plugins/PackageToJS/Templates/platforms/node.js b/Plugins/PackageToJS/Templates/platforms/node.js index 4d29fc33f..3e1253965 100644 --- a/Plugins/PackageToJS/Templates/platforms/node.js +++ b/Plugins/PackageToJS/Templates/platforms/node.js @@ -113,7 +113,7 @@ class DefaultNodeThreadRegistry { /* #endif */ /** @type {import('./node.d.ts').defaultNodeSetup} */ -export async function defaultNodeSetup(options) { +export async function defaultNodeSetup(options = {}) { const path = await import("node:path"); const { fileURLToPath } = await import("node:url"); const { readFile } = await import("node:fs/promises") @@ -131,15 +131,17 @@ export async function defaultNodeSetup(options) { new PreopenDirectory("/", rootFs), ], { debug: false }) const pkgDir = path.dirname(path.dirname(fileURLToPath(import.meta.url))) - const module = await WebAssembly.compile(await readFile(path.join(pkgDir, MODULE_PATH))) + const module = await WebAssembly.compile(new Uint8Array(await readFile(path.join(pkgDir, MODULE_PATH)))) /* #if USE_SHARED_MEMORY */ const memory = new WebAssembly.Memory(MEMORY_TYPE); - const threadChannel = new DefaultNodeThreadRegistry(options.spawnWorker) + const threadChannel = new DefaultNodeThreadRegistry(options.spawnWorker || createDefaultWorkerFactory()) /* #endif */ return { module, +/* #if HAS_IMPORTS */ getImports() { return {} }, +/* #endif */ /* #if IS_WASI */ wasi: Object.assign(wasi, { setInstance(instance) { diff --git a/Plugins/PackageToJS/Templates/runtime.mjs b/Plugins/PackageToJS/Templates/runtime.mjs index 6f4abe687..d79275476 100644 --- a/Plugins/PackageToJS/Templates/runtime.mjs +++ b/Plugins/PackageToJS/Templates/runtime.mjs @@ -1,6 +1,6 @@ /// Memory lifetime of closures in Swift are managed by Swift side class SwiftClosureDeallocator { - constructor(exports) { + constructor(exports$1) { if (typeof FinalizationRegistry === "undefined") { throw new Error("The Swift part of JavaScriptKit was configured to require " + "the availability of JavaScript WeakRefs. Please build " + @@ -8,7 +8,7 @@ class SwiftClosureDeallocator { "disable features that use WeakRefs."); } this.functionRegistry = new FinalizationRegistry((id) => { - exports.swjs_free_host_function(id); + exports$1.swjs_free_host_function(id); }); } track(func, func_ref) { @@ -30,11 +30,11 @@ const decode = (kind, payload1, payload2, objectSpace) => { case 1: return true; } + // falls through case 2 /* Kind.Number */: return payload2; case 1 /* Kind.String */: case 3 /* Kind.Object */: - case 6 /* Kind.Function */: case 7 /* Kind.Symbol */: case 8 /* Kind.BigInt */: return objectSpace.getObject(payload1); @@ -100,7 +100,7 @@ const writeAndReturnKindBits = (value, payload1_ptr, payload2_ptr, is_exception, return writeRef(3 /* Kind.Object */); } case "function": { - return writeRef(6 /* Kind.Function */); + return writeRef(3 /* Kind.Object */); } case "symbol": { return writeRef(7 /* Kind.Symbol */); @@ -127,12 +127,12 @@ class ITCInterface { } send(sendingObject, transferringObjects, sendingContext) { const object = this.memory.getObject(sendingObject); - const transfer = transferringObjects.map(ref => this.memory.getObject(ref)); + const transfer = transferringObjects.map((ref) => this.memory.getObject(ref)); return { object, sendingContext, transfer }; } sendObjects(sendingObjects, transferringObjects, sendingContext) { - const objects = sendingObjects.map(ref => this.memory.getObject(ref)); - const transfer = transferringObjects.map(ref => this.memory.getObject(ref)); + const objects = sendingObjects.map((ref) => this.memory.getObject(ref)); + const transfer = transferringObjects.map((ref) => this.memory.getObject(ref)); return { object: objects, sendingContext, transfer }; } release(objectRef) { @@ -169,7 +169,9 @@ class MessageBroker { this.handlers.onResponse(message); return; } - const transfer = message.data.response.ok ? message.data.response.value.transfer : []; + const transfer = message.data.response.ok + ? message.data.response.value.transfer + : []; if ("postMessageToWorkerThread" in this.threadChannel) { // The response is for another worker thread sent from the main thread this.threadChannel.postMessageToWorkerThread(message.data.sourceTid, message, transfer); @@ -187,7 +189,7 @@ class MessageBroker { this.handlers.onRequest(message); } else if ("postMessageToWorkerThread" in this.threadChannel) { - // Receive a request from a worker thread to other worker on main thread. + // Receive a request from a worker thread to other worker on main thread. // Proxy the request to the target worker thread. this.threadChannel.postMessageToWorkerThread(message.data.targetTid, message, []); } @@ -203,7 +205,9 @@ class MessageBroker { else if ("postMessageToWorkerThread" in this.threadChannel) { // Receive a response from a worker thread to other worker on main thread. // Proxy the response to the target worker thread. - const transfer = message.data.response.ok ? message.data.response.value.transfer : []; + const transfer = message.data.response.ok + ? message.data.response.value.transfer + : []; this.threadChannel.postMessageToWorkerThread(message.data.sourceTid, message, transfer); } else if ("postMessageToMainThread" in this.threadChannel) { @@ -214,7 +218,14 @@ class MessageBroker { } function serializeError(error) { if (error instanceof Error) { - return { isError: true, value: { message: error.message, name: error.name, stack: error.stack } }; + return { + isError: true, + value: { + message: error.message, + name: error.name, + stack: error.stack, + }, + }; } return { isError: false, value: error }; } @@ -225,19 +236,7 @@ function deserializeError(error) { return error.value; } -let globalVariable; -if (typeof globalThis !== "undefined") { - globalVariable = globalThis; -} -else if (typeof window !== "undefined") { - globalVariable = window; -} -else if (typeof global !== "undefined") { - globalVariable = global; -} -else if (typeof self !== "undefined") { - globalVariable = self; -} +const globalVariable = globalThis; class JSObjectSpace { constructor() { @@ -313,7 +312,8 @@ class SwiftRuntime { // 1. It may not be available in the global scope if the context is not cross-origin isolated. // 2. The underlying buffer may be still backed by SAB even if the context is not cross-origin // isolated (e.g. localhost on Chrome on Android). - if (Object.getPrototypeOf(wasmMemory.buffer).constructor.name === "SharedArrayBuffer") { + if (Object.getPrototypeOf(wasmMemory.buffer).constructor.name === + "SharedArrayBuffer") { // When the wasm memory is backed by a SharedArrayBuffer, growing the memory // doesn't invalidate the data view by setting the byte length to 0. Instead, // the data view points to an old buffer after growing the memory. So we have @@ -464,7 +464,10 @@ class SwiftRuntime { returnValue = { ok: true, value: result }; } catch (error) { - returnValue = { ok: false, error: serializeError(error) }; + returnValue = { + ok: false, + error: serializeError(error), + }; } const responseMessage = { type: "response", @@ -480,7 +483,7 @@ class SwiftRuntime { catch (error) { responseMessage.data.response = { ok: false, - error: serializeError(new TypeError(`Failed to serialize message: ${error}`)) + error: serializeError(new TypeError(`Failed to serialize message: ${error}`)), }; newBroker.reply(responseMessage); } @@ -495,7 +498,7 @@ class SwiftRuntime { const errorObject = this.memory.retain(error); this.exports.swjs_receive_error(errorObject, message.data.context); } - } + }, }); broker = newBroker; return newBroker; @@ -533,21 +536,19 @@ class SwiftRuntime { this.getDataView().setUint32(bytes_ptr_result, bytes_ptr, true); return bytes.length; }, - swjs_decode_string: ( + swjs_decode_string: // NOTE: TextDecoder can't decode typed arrays backed by SharedArrayBuffer this.options.sharedMemory == true - ? ((bytes_ptr, length) => { - const bytes = this.getUint8Array() - .slice(bytes_ptr, bytes_ptr + length); + ? (bytes_ptr, length) => { + const bytes = this.getUint8Array().slice(bytes_ptr, bytes_ptr + length); const string = this.textDecoder.decode(bytes); return this.memory.retain(string); - }) - : ((bytes_ptr, length) => { - const bytes = this.getUint8Array() - .subarray(bytes_ptr, bytes_ptr + length); + } + : (bytes_ptr, length) => { + const bytes = this.getUint8Array().subarray(bytes_ptr, bytes_ptr + length); const string = this.textDecoder.decode(bytes); return this.memory.retain(string); - })), + }, swjs_load_string: (ref, buffer) => { const bytes = this.memory.getObject(ref); this.getUint8Array().set(bytes, buffer); @@ -555,7 +556,7 @@ class SwiftRuntime { swjs_call_function: (ref, argv, argc, payload1_ptr, payload2_ptr) => { const memory = this.memory; const func = memory.getObject(ref); - let result = undefined; + let result; try { const args = decodeArray(argv, argc, this.getDataView(), memory); result = func(...args); @@ -590,9 +591,8 @@ class SwiftRuntime { const memory = this.memory; const obj = memory.getObject(obj_ref); const func = memory.getObject(func_ref); - let result = undefined; const args = decodeArray(argv, argc, this.getDataView(), memory); - result = func.apply(obj, args); + const result = func.apply(obj, args); return writeAndReturnKindBits(result, payload1_ptr, payload2_ptr, false, this.getDataView(), this.memory); }, swjs_call_new: (ref, argv, argc) => { @@ -659,7 +659,9 @@ class SwiftRuntime { // Call `.slice()` to copy the memory return this.memory.retain(array.slice()); }, - swjs_create_object: () => { return this.memory.retain({}); }, + swjs_create_object: () => { + return this.memory.retain({}); + }, swjs_load_typed_array: (ref, buffer) => { const memory = this.memory; const typedArray = memory.getObject(ref); @@ -684,8 +686,8 @@ class SwiftRuntime { request: { method: "release", parameters: [ref], - } - } + }, + }, }); }, swjs_i64_to_bigint: (value, signed) => { @@ -709,17 +711,23 @@ class SwiftRuntime { swjs_i64_to_bigint_slow: (lower, upper, signed) => { const value = BigInt.asUintN(32, BigInt(lower)) + (BigInt.asUintN(32, BigInt(upper)) << BigInt(32)); - return this.memory.retain(signed ? BigInt.asIntN(64, value) : BigInt.asUintN(64, value)); + return this.memory.retain(signed + ? BigInt.asIntN(64, value) + : BigInt.asUintN(64, value)); }, swjs_unsafe_event_loop_yield: () => { throw new UnsafeEventLoopYield(); }, swjs_send_job_to_main_thread: (unowned_job) => { - this.postMessageToMainThread({ type: "job", data: unowned_job }); + this.postMessageToMainThread({ + type: "job", + data: unowned_job, + }); }, swjs_listen_message_from_main_thread: () => { const threadChannel = this.options.threadChannel; - if (!(threadChannel && "listenMessageFromMainThread" in threadChannel)) { + if (!(threadChannel && + "listenMessageFromMainThread" in threadChannel)) { throw new Error("listenMessageFromMainThread is not set in options given to SwiftRuntime. Please set it to listen to wake events from the main thread."); } const broker = getMessageBroker(threadChannel); @@ -736,9 +744,10 @@ class SwiftRuntime { broker.onReceivingResponse(message); break; } - default: + default: { const unknownMessage = message; throw new Error(`Unknown message type: ${unknownMessage}`); + } } }); }, @@ -747,7 +756,8 @@ class SwiftRuntime { }, swjs_listen_message_from_worker_thread: (tid) => { const threadChannel = this.options.threadChannel; - if (!(threadChannel && "listenMessageFromWorkerThread" in threadChannel)) { + if (!(threadChannel && + "listenMessageFromWorkerThread" in threadChannel)) { throw new Error("listenMessageFromWorkerThread is not set in options given to SwiftRuntime. Please set it to listen to jobs from worker threads."); } const broker = getMessageBroker(threadChannel); @@ -764,9 +774,10 @@ class SwiftRuntime { broker.onReceivingResponse(message); break; } - default: + default: { const unknownMessage = message; throw new Error(`Unknown message type: ${unknownMessage}`); + } } }); }, @@ -796,9 +807,13 @@ class SwiftRuntime { context: sending_context, request: { method: "send", - parameters: [sending_object, transferringObjects, sending_context], - } - } + parameters: [ + sending_object, + transferringObjects, + sending_context, + ], + }, + }, }); }, swjs_request_sending_objects: (sending_objects, sending_objects_count, transferring_objects, transferring_objects_count, object_source_tid, sending_context) => { @@ -818,9 +833,13 @@ class SwiftRuntime { context: sending_context, request: { method: "sendObjects", - parameters: [sendingObjects, transferringObjects, sending_context], - } - } + parameters: [ + sendingObjects, + transferringObjects, + sending_context, + ], + }, + }, }); }, }; diff --git a/Plugins/PackageToJS/Templates/test.d.ts b/Plugins/PackageToJS/Templates/test.d.ts index 21383997b..4c6741a75 100644 --- a/Plugins/PackageToJS/Templates/test.d.ts +++ b/Plugins/PackageToJS/Templates/test.d.ts @@ -7,10 +7,35 @@ export type SetupOptionsFn = ( } ) => Promise +/** + * Functions to be exposed to the browser context via Playwright's page.exposeFunction. + * Note: All functions are treated as async from the browser's perspective and will + * return Promises when called from Swift/WebAssembly via JavaScriptKit. + */ +export type ExposedFunctions = Record Promise> + +/** + * A function that receives the Playwright Page object and returns exposed functions. + * This allows the exposed functions to interact with the browser page (click, query DOM, etc.) + * Can also be used for async initialization before returning the functions. + * + * @param page - The Playwright Page object for browser interaction + * @returns An object mapping function names to async functions, or a Promise resolving to such an object + */ +export type ExposedFunctionsFn = (page: import('playwright').Page) => ExposedFunctions | Promise + export function testBrowser( options: { + /** Path to the prelude script to be injected before tests run */ preludeScript?: string, + /** Command-line arguments to pass to the test runner */ args?: string[], + /** Options for Playwright browser */ + playwright?: { + browser?: string, + launchOptions?: import("playwright").LaunchOptions + onPageLoad?: (page: import("playwright").Page) => Promise + } } ): Promise diff --git a/Plugins/PackageToJS/Templates/test.js b/Plugins/PackageToJS/Templates/test.js index 518dacf20..606040b04 100644 --- a/Plugins/PackageToJS/Templates/test.js +++ b/Plugins/PackageToJS/Templates/test.js @@ -96,19 +96,24 @@ Please run the following command to install it: process.exit(1); } })(); - const browser = await playwright.chromium.launch(); + const browser = await playwright[options.playwright?.browser ?? "chromium"].launch(options.playwright?.launchOptions ?? {}); const context = await browser.newContext(); const page = await context.newPage(); - + // Allow the user to customize the page before it's loaded, for defining custom export functions + if (options.playwright?.onPageLoad) { + await options.playwright.onPageLoad(page); + } // Forward console messages in the page to the Node.js console 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/Plugins/PackageToJS/Templates/tsconfig.json b/Plugins/PackageToJS/Templates/tsconfig.json index ac3a2b01e..91fe8516f 100644 --- a/Plugins/PackageToJS/Templates/tsconfig.json +++ b/Plugins/PackageToJS/Templates/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { "module": "esnext", + "lib": ["es2017", "dom"], "noEmit": true, "allowJs": true, "skipLibCheck": true, diff --git a/Plugins/PackageToJS/Tests/ExampleTests.swift b/Plugins/PackageToJS/Tests/ExampleTests.swift index 4de602f15..d26832771 100644 --- a/Plugins/PackageToJS/Tests/ExampleTests.swift +++ b/Plugins/PackageToJS/Tests/ExampleTests.swift @@ -7,8 +7,8 @@ extension Trait where Self == ConditionTrait { static var requireSwiftSDK: ConditionTrait { .enabled( if: ProcessInfo.processInfo.environment["SWIFT_SDK_ID"] != nil - && ProcessInfo.processInfo.environment["SWIFT_PATH"] != nil, - "Requires SWIFT_SDK_ID and SWIFT_PATH environment variables" + && ProcessInfo.processInfo.environment["SWIFT_BIN_PATH"] != nil, + "Requires SWIFT_SDK_ID and SWIFT_BIN_PATH environment variables" ) } @@ -16,7 +16,7 @@ extension Trait where Self == ConditionTrait { .enabled( if: { guard let swiftSDKID = ProcessInfo.processInfo.environment["SWIFT_SDK_ID"], - ProcessInfo.processInfo.environment["SWIFT_PATH"] != nil + ProcessInfo.processInfo.environment["SWIFT_BIN_PATH"] != nil else { return false } @@ -32,22 +32,22 @@ extension Trait where Self == ConditionTrait { } return sanityCheckCompatibility(triple: triple) }(), - "Requires SWIFT_SDK_ID and SWIFT_PATH environment variables" + "Requires SWIFT_SDK_ID and SWIFT_BIN_PATH environment variables" ) } static func requireEmbeddedSwiftInToolchain(triple: String) -> ConditionTrait { - // Check if $SWIFT_PATH/../lib/swift/embedded/wasm32-unknown-none-wasm/ exists + // Check if $SWIFT_BIN_PATH/../lib/swift/embedded/wasm32-unknown-none-wasm/ exists return .enabled( if: { - guard let swiftPath = ProcessInfo.processInfo.environment["SWIFT_PATH"] else { + guard let swiftPath = ProcessInfo.processInfo.environment["SWIFT_BIN_PATH"] else { return false } let embeddedPath = URL(fileURLWithPath: swiftPath).deletingLastPathComponent() .appending(path: "lib/swift/embedded/\(triple)") return FileManager.default.fileExists(atPath: embeddedPath.path) }(), - "Requires embedded Swift SDK under $SWIFT_PATH/../lib/swift/embedded" + "Requires embedded Swift SDK under $SWIFT_BIN_PATH/../lib/swift/embedded" ) } @@ -75,11 +75,19 @@ extension Trait where Self == ConditionTrait { return false } } - guard let swiftPath = ProcessInfo.processInfo.environment["SWIFT_PATH"], + guard let swiftPath = ProcessInfo.processInfo.environment["SWIFT_BIN_PATH"], let swiftSDKID = ProcessInfo.processInfo.environment["SWIFT_SDK_ID"] else { return false } + guard + ["wasm32-unknown-wasi", "wasm32-unknown-wasip1"].contains(where: { + swiftSDKID.hasSuffix($0) + }) + else { + // Only non-threads SDKs are supported for embedded in Swift SDK + return false + } let embeddedSDKID = "\(swiftSDKID)-embedded" return isSwiftSDKAvailable(embeddedSDKID, swiftPath: swiftPath) }(), @@ -94,7 +102,7 @@ extension Trait where Self == ConditionTrait { } static func getSwiftPath() -> String? { - ProcessInfo.processInfo.environment["SWIFT_PATH"] + ProcessInfo.processInfo.environment["SWIFT_BIN_PATH"] } static func getEmbeddedSwiftSDKID() -> String? { @@ -119,6 +127,7 @@ extension Trait where Self == ConditionTrait { ".vscode", ".build", "node_modules", + "Tests/TemporaryDirectory", ] let enumerator = FileManager.default.enumerator(atPath: repoPath.path)! @@ -206,6 +215,7 @@ extension Trait where Self == ConditionTrait { Swift package should build successfully, check \(destination.appending(path: path).path) for details stdout: \(stdoutPath.path) stderr: \(stderrPath.path) + arguments: \(args) \((try? String(contentsOf: stdoutPath, encoding: .utf8)) ?? "<>") \((try? String(contentsOf: stderrPath, encoding: .utf8)) ?? "<>") @@ -223,6 +233,15 @@ extension Trait where Self == ConditionTrait { } } + /// FIXME: swift-testing uses too much stack space, so we need to increase the stack size for tests using swift-testing. + static var stackSizeLinkerFlags: [String] { + [ + "--toolset", + URL(fileURLWithPath: #filePath).deletingLastPathComponent().appending(path: "Inputs/example-toolset.json") + .path, + ] + } + @Test(.requireSwiftSDK) func basic() throws { let swiftSDKID = try #require(Self.getSwiftSDKID()) @@ -237,6 +256,9 @@ extension Trait where Self == ConditionTrait { } } + // FIXME: This test fails on Swift 6.3 and later due to memory corruption + // Enable it back when https://github.com/swiftlang/swift-driver/pull/1987 is included in the snapshot + #if !compiler(>=6.3) @Test(.requireSwiftSDK) func testing() throws { let swiftSDKID = try #require(Self.getSwiftSDKID()) @@ -304,6 +326,7 @@ extension Trait where Self == ConditionTrait { } } #endif + #endif // compiler(>=6.3) @Test(.requireSwiftSDK(triple: "wasm32-unknown-wasip1-threads")) func multithreading() throws { @@ -329,18 +352,8 @@ extension Trait where Self == ConditionTrait { } } - @Test(.requireEmbeddedSwiftInToolchain(triple: "wasm32-unknown-none-wasm")) - func embeddedWasmUnknownNone() throws { - try withPackage(at: "Examples/Embedded") { packageDir, _, runSwift in - try runSwift( - ["package", "--triple", "wasm32-unknown-none-wasm", "js", "-c", "release"], - [ - "JAVASCRIPTKIT_EXPERIMENTAL_EMBEDDED_WASM": "true" - ] - ) - } - } - + // FIXME: This test fails on the current main snapshot + #if !compiler(>=6.3) @Test(.requireEmbeddedSwiftInSwiftSDK()) func embeddedWasmUnknownWasi() throws { let swiftSDKID = try #require(Self.getEmbeddedSwiftSDKID()) @@ -353,6 +366,7 @@ extension Trait where Self == ConditionTrait { ) } } + #endif // compiler(>=6.3) @Test(.requireSwiftSDK) func continuationLeakInTest_XCTest() throws { @@ -378,4 +392,47 @@ extension Trait where Self == ConditionTrait { } } #endif + + @Test(.requireSwiftSDK) + func playwrightOnPageLoad_XCTest() throws { + let swiftSDKID = try #require(Self.getSwiftSDKID()) + try withPackage( + at: "Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/XCTest", + assertTerminationStatus: { $0 == 0 } + ) { packageDir, runProcess, runSwift in + try runProcess(which("npm"), ["install"], [:]) + try runProcess(which("npx"), ["playwright", "install", "chromium-headless-shell"], [:]) + + try runSwift( + ["package", "--disable-sandbox"] + Self.stackSizeLinkerFlags + [ + "--swift-sdk", swiftSDKID, "js", "test", "--environment", "browser", + "--playwright-expose", "../expose.js", + ], + [:] + ) + } + } + + #if compiler(>=6.1) + // TODO: Remove triple restriction once swift-testing is shipped in p1-threads SDK + @Test(.requireSwiftSDK(triple: "wasm32-unknown-wasi")) + func playwrightOnPageLoad_SwiftTesting() throws { + let swiftSDKID = try #require(Self.getSwiftSDKID()) + try withPackage( + at: "Plugins/PackageToJS/Fixtures/PlaywrightOnPageLoadTest/SwiftTesting", + assertTerminationStatus: { $0 == 0 } + ) { packageDir, runProcess, runSwift in + try runProcess(which("npm"), ["install"], [:]) + try runProcess(which("npx"), ["playwright", "install", "chromium-headless-shell"], [:]) + + try runSwift( + [ + "package", "--disable-sandbox", "--swift-sdk", swiftSDKID, "js", "test", "--environment", "browser", + "--playwright-expose", "../expose.js", + ], + [:] + ) + } + } + #endif } diff --git a/Plugins/PackageToJS/Tests/Inputs/example-toolset.json b/Plugins/PackageToJS/Tests/Inputs/example-toolset.json new file mode 100644 index 000000000..307777db3 --- /dev/null +++ b/Plugins/PackageToJS/Tests/Inputs/example-toolset.json @@ -0,0 +1,6 @@ +{ + "schemaVersion" : "1.0", + "linker": { + "extraCLIOptions": ["--stack-first", "-z", "stack-size=524288", "--global-base=524288"] + } +} diff --git a/Plugins/PackageToJS/Tests/MiniMakeTests.swift b/Plugins/PackageToJS/Tests/MiniMakeTests.swift index c0bba29c7..140f28805 100644 --- a/Plugins/PackageToJS/Tests/MiniMakeTests.swift +++ b/Plugins/PackageToJS/Tests/MiniMakeTests.swift @@ -4,6 +4,67 @@ import Testing @testable import PackageToJS @Suite struct MiniMakeTests { + final class InMemoryFileSystem: MiniMakeFileSystem { + struct FileEntry { + var content: Data + var modificationDate: Date + var isDirectory: Bool + } + private var storage: [URL: FileEntry] = [:] + + struct MonotonicDateGenerator { + private var currentDate: Date + + init(startingFrom date: Date = Date()) { + self.currentDate = date + } + + mutating func next() -> Date { + currentDate = currentDate.addingTimeInterval(1) + return currentDate + } + } + var dateGenerator = MonotonicDateGenerator() + + // MARK: - MiniMakeFileSystem conformance + + func removeItem(at url: URL) throws { + storage.removeValue(forKey: url) + } + + func fileExists(at url: URL) -> Bool { + return storage[url] != nil + } + + func fileExists(at url: URL) -> (exists: Bool, isDirectory: Bool) { + if let entry = storage[url] { + return (true, entry.isDirectory) + } else { + return (false, false) + } + } + + func modificationDate(of url: URL) throws -> Date? { + return storage[url]?.modificationDate + } + + func writeFile(at url: URL, content: Data) { + storage[url] = FileEntry(content: content, modificationDate: dateGenerator.next(), isDirectory: false) + } + + // MARK: - Helpers for tests + + func touch(_ url: URL) { + let date = dateGenerator.next() + if var entry = storage[url] { + entry.modificationDate = date + storage[url] = entry + } else { + storage[url] = FileEntry(content: Data(), modificationDate: date, isDirectory: false) + } + } + } + // Test basic task management functionality @Test func basicTaskManagement() throws { try withTemporaryDirectory { tempDir, _ in @@ -114,7 +175,11 @@ import Testing // Test that rebuilds are controlled by timestamps @Test func timestampBasedRebuild() throws { try withTemporaryDirectory { tempDir, _ in - var make = MiniMake(printProgress: { _, _ in }) + let fs = InMemoryFileSystem() + var make = MiniMake( + fileSystem: fs, + printProgress: { _, _ in } + ) let prefix = BuildPath(prefix: "PREFIX") let scope = MiniMake.VariableScope(variables: [ "PREFIX": tempDir.path @@ -123,25 +188,25 @@ import Testing let output = prefix.appending(path: "output.txt") var buildCount = 0 - try "Initial".write(toFile: scope.resolve(path: input).path, atomically: true, encoding: .utf8) + // Create initial input file + fs.touch(scope.resolve(path: input)) let task = make.addTask(inputFiles: [input], output: output) { task, scope in buildCount += 1 - let content = try String(contentsOfFile: scope.resolve(path: task.inputs[0]).path, encoding: .utf8) - try content.write(toFile: scope.resolve(path: task.output).path, atomically: true, encoding: .utf8) + fs.touch(scope.resolve(path: task.output)) } // First build - try make.build(output: task, scope: scope) + #expect(throws: Never.self) { try make.build(output: task, scope: scope) } #expect(buildCount == 1, "First build should occur") // Second build without changes - try make.build(output: task, scope: scope) + #expect(throws: Never.self) { try make.build(output: task, scope: scope) } #expect(buildCount == 1, "No rebuild should occur if input is not modified") // Modify input and rebuild - try "Modified".write(toFile: scope.resolve(path: input).path, atomically: true, encoding: .utf8) - try make.build(output: task, scope: scope) + fs.touch(scope.resolve(path: input)) + #expect(throws: Never.self) { try make.build(output: task, scope: scope) } #expect(buildCount == 2, "Should rebuild when input is modified") } } diff --git a/Plugins/PackageToJS/Tests/PackagingPlannerTests.swift b/Plugins/PackageToJS/Tests/PackagingPlannerTests.swift index 03fc4c9cc..3e0d67a3e 100644 --- a/Plugins/PackageToJS/Tests/PackagingPlannerTests.swift +++ b/Plugins/PackageToJS/Tests/PackagingPlannerTests.swift @@ -65,8 +65,7 @@ import Testing packageId: "test", intermediatesDir: BuildPath(prefix: "INTERMEDIATES"), selfPackageDir: BuildPath(prefix: "SELF_PACKAGE"), - exportedSkeletons: [], - importedSkeletons: [], + skeletons: [], outputDir: BuildPath(prefix: "OUTPUT"), wasmProductArtifact: BuildPath(prefix: "WASM_PRODUCT_ARTIFACT"), wasmFilename: "main.wasm", @@ -96,8 +95,7 @@ import Testing packageId: "test", intermediatesDir: BuildPath(prefix: "INTERMEDIATES"), selfPackageDir: BuildPath(prefix: "SELF_PACKAGE"), - exportedSkeletons: [], - importedSkeletons: [], + skeletons: [], outputDir: BuildPath(prefix: "OUTPUT"), wasmProductArtifact: BuildPath(prefix: "WASM_PRODUCT_ARTIFACT"), wasmFilename: "main.wasm", diff --git a/Plugins/PackageToJS/Tests/TemplatesTests.swift b/Plugins/PackageToJS/Tests/TemplatesTests.swift index e885eb087..5a27259c3 100644 --- a/Plugins/PackageToJS/Tests/TemplatesTests.swift +++ b/Plugins/PackageToJS/Tests/TemplatesTests.swift @@ -3,18 +3,66 @@ import Foundation @testable import PackageToJS @Suite struct TemplatesTests { - static let templatesPath = URL(fileURLWithPath: #filePath) + static let pluginPackagePath = URL(fileURLWithPath: #filePath) .deletingLastPathComponent() .deletingLastPathComponent() + static let templatesPath = + pluginPackagePath .appendingPathComponent("Templates") + static let localTemporaryDirectory = + pluginPackagePath + .appendingPathComponent("Tests") + .appendingPathComponent("TemporaryDirectory") /// `npx tsc -p Templates/tsconfig.json` - @Test func tscCheck() throws { - let tsc = Process() - tsc.executableURL = try which("npx") - tsc.arguments = ["tsc", "-p", Self.templatesPath.appending(path: "tsconfig.json").path] - try tsc.run() - tsc.waitUntilExit() - #expect(tsc.terminationStatus == 0) + /// Test both node and browser platform variants + @Test(arguments: ["node", "browser"]) + func tscCheck(platform: String) throws { + // Use a local temporary directory to place instantiated templates so that + // they can reference repo-root node_modules packages like @types/node. + try FileManager.default.createDirectory( + at: Self.localTemporaryDirectory, + withIntermediateDirectories: true, + attributes: nil + ) + try withTemporaryDirectory(prefixDirectory: Self.localTemporaryDirectory) { tempDir, _ in + let destination = tempDir.appending(path: Self.templatesPath.lastPathComponent) + // Copy entire templates folder to temp location + try FileManager.default.copyItem(at: Self.templatesPath, to: destination) + + // Setup preprocessing conditions + let conditions: [String: Bool] = [ + "USE_SHARED_MEMORY": false, + "IS_WASI": true, + "USE_WASI_CDN": false, + "HAS_BRIDGE": false, + "HAS_IMPORTS": false, + "TARGET_DEFAULT_PLATFORM_NODE": platform == "node", + "TARGET_DEFAULT_PLATFORM_BROWSER": platform == "browser", + ] + let preprocessOptions = PreprocessOptions(conditions: conditions, substitutions: [:]) + + // Preprocess all JS and TS files in-place + let enumerator = FileManager.default.enumerator(at: destination, includingPropertiesForKeys: nil) + while let fileURL = enumerator?.nextObject() as? URL { + guard !fileURL.hasDirectoryPath, + fileURL.pathExtension == "js" || fileURL.pathExtension == "ts" + else { + continue + } + + let content = try String(contentsOf: fileURL, encoding: .utf8) + let preprocessed = try preprocess(source: content, file: fileURL.path, options: preprocessOptions) + try preprocessed.write(to: fileURL, atomically: true, encoding: .utf8) + } + + // Run TypeScript on the preprocessed files + let tsc = Process() + tsc.executableURL = try which("npx") + tsc.arguments = ["tsc", "-p", destination.appending(path: "tsconfig.json").path] + try tsc.run() + tsc.waitUntilExit() + #expect(tsc.terminationStatus == 0) + } } } diff --git a/Plugins/PackageToJS/Tests/TemporaryDirectory.swift b/Plugins/PackageToJS/Tests/TemporaryDirectory.swift index 199380fac..c08b044f1 100644 --- a/Plugins/PackageToJS/Tests/TemporaryDirectory.swift +++ b/Plugins/PackageToJS/Tests/TemporaryDirectory.swift @@ -4,9 +4,12 @@ struct MakeTemporaryDirectoryError: Error { let error: CInt } -internal func withTemporaryDirectory(body: (URL, _ retain: inout Bool) throws -> T) throws -> T { +internal func withTemporaryDirectory( + prefixDirectory: URL = FileManager.default.temporaryDirectory, + body: (URL, _ retain: inout Bool) throws -> T +) throws -> T { // Create a temporary directory using mkdtemp - var template = FileManager.default.temporaryDirectory.appendingPathComponent("PackageToJSTests.XXXXXX").path + var template = prefixDirectory.appendingPathComponent("PackageToJSTests.XXXXXX").path return try template.withUTF8 { template in let copy = UnsafeMutableBufferPointer.allocate(capacity: template.count + 1) template.copyBytes(to: copy) diff --git a/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_debug.json b/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_debug.json index 13768da75..49cee1f90 100644 --- a/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_debug.json +++ b/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_debug.json @@ -48,7 +48,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/index.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -65,7 +65,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/index.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -82,7 +82,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/instantiate.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -99,7 +99,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/instantiate.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -128,7 +128,7 @@ "$SELF_PACKAGE\/Plugins\/PackageToJS\/Templates\/package.json" ], "output" : "$OUTPUT\/package.json", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT" ] @@ -155,7 +155,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -172,7 +172,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -189,7 +189,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.worker.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -206,7 +206,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/node.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -223,7 +223,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/node.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -240,7 +240,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/runtime.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -257,7 +257,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/runtime.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", diff --git a/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_release.json b/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_release.json index ccfbc35cc..6b1e1090c 100644 --- a/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_release.json +++ b/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_release.json @@ -62,7 +62,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/index.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -79,7 +79,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/index.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -96,7 +96,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/instantiate.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -113,7 +113,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/instantiate.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -143,7 +143,7 @@ "$SELF_PACKAGE\/Plugins\/PackageToJS\/Templates\/package.json" ], "output" : "$OUTPUT\/package.json", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT" ] @@ -170,7 +170,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -187,7 +187,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -204,7 +204,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.worker.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -221,7 +221,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/node.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -238,7 +238,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/node.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -255,7 +255,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/runtime.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -272,7 +272,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/runtime.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", diff --git a/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_release_dwarf.json b/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_release_dwarf.json index 13768da75..49cee1f90 100644 --- a/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_release_dwarf.json +++ b/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_release_dwarf.json @@ -48,7 +48,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/index.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -65,7 +65,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/index.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -82,7 +82,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/instantiate.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -99,7 +99,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/instantiate.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -128,7 +128,7 @@ "$SELF_PACKAGE\/Plugins\/PackageToJS\/Templates\/package.json" ], "output" : "$OUTPUT\/package.json", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT" ] @@ -155,7 +155,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -172,7 +172,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -189,7 +189,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.worker.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -206,7 +206,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/node.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -223,7 +223,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/node.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -240,7 +240,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/runtime.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -257,7 +257,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/runtime.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", diff --git a/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_release_name.json b/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_release_name.json index ccfbc35cc..6b1e1090c 100644 --- a/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_release_name.json +++ b/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_release_name.json @@ -62,7 +62,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/index.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -79,7 +79,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/index.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -96,7 +96,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/instantiate.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -113,7 +113,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/instantiate.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -143,7 +143,7 @@ "$SELF_PACKAGE\/Plugins\/PackageToJS\/Templates\/package.json" ], "output" : "$OUTPUT\/package.json", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT" ] @@ -170,7 +170,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -187,7 +187,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -204,7 +204,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.worker.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -221,7 +221,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/node.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -238,7 +238,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/node.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -255,7 +255,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/runtime.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -272,7 +272,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/runtime.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", diff --git a/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_release_no_optimize.json b/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_release_no_optimize.json index 13768da75..49cee1f90 100644 --- a/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_release_no_optimize.json +++ b/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planBuild_release_no_optimize.json @@ -48,7 +48,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/index.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -65,7 +65,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/index.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -82,7 +82,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/instantiate.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -99,7 +99,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/instantiate.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -128,7 +128,7 @@ "$SELF_PACKAGE\/Plugins\/PackageToJS\/Templates\/package.json" ], "output" : "$OUTPUT\/package.json", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT" ] @@ -155,7 +155,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -172,7 +172,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -189,7 +189,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.worker.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -206,7 +206,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/node.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -223,7 +223,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/node.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -240,7 +240,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/runtime.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -257,7 +257,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/runtime.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", diff --git a/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planTestBuild.json b/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planTestBuild.json index 89425dc83..5f16f6e8e 100644 --- a/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planTestBuild.json +++ b/Plugins/PackageToJS/Tests/__Snapshots__/PackagingPlannerTests/planTestBuild.json @@ -73,7 +73,7 @@ "$SELF_PACKAGE\/Plugins\/PackageToJS\/Templates\/bin\/test.js" ], "output" : "$OUTPUT\/bin\/test.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/bin" @@ -89,7 +89,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/index.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -106,7 +106,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/index.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -123,7 +123,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/instantiate.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -140,7 +140,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/instantiate.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -169,7 +169,7 @@ "$SELF_PACKAGE\/Plugins\/PackageToJS\/Templates\/package.json" ], "output" : "$OUTPUT\/package.json", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT" ] @@ -196,7 +196,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -213,7 +213,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -230,7 +230,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/browser.worker.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -247,7 +247,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/node.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -264,7 +264,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/platforms\/node.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -281,7 +281,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/runtime.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -298,7 +298,7 @@ "$INTERMEDIATES\/wasm-imports.json" ], "output" : "$OUTPUT\/runtime.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/platforms", @@ -314,7 +314,7 @@ "$SELF_PACKAGE\/Plugins\/PackageToJS\/Templates\/test.browser.html" ], "output" : "$OUTPUT\/test.browser.html", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/bin" @@ -329,7 +329,7 @@ "$SELF_PACKAGE\/Plugins\/PackageToJS\/Templates\/test.d.ts" ], "output" : "$OUTPUT\/test.d.ts", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/bin" @@ -344,7 +344,7 @@ "$SELF_PACKAGE\/Plugins\/PackageToJS\/Templates\/test.js" ], "output" : "$OUTPUT\/test.js", - "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlVTRV9TSEFSRURfTUVNT1JZIjpmYWxzZSwiVVNFX1dBU0lfQ0ROIjpmYWxzZX0sInN1YnN0aXR1dGlvbnMiOnsiUEFDS0FHRV9UT19KU19NT0RVTEVfUEFUSCI6Im1haW4ud2FzbSIsIlBBQ0tBR0VfVE9fSlNfUEFDS0FHRV9OQU1FIjoidGVzdCJ9fQ==", + "salt" : "eyJjb25kaXRpb25zIjp7IkhBU19CUklER0UiOmZhbHNlLCJIQVNfSU1QT1JUUyI6ZmFsc2UsIklTX1dBU0kiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX0JST1dTRVIiOnRydWUsIlRBUkdFVF9ERUZBVUxUX1BMQVRGT1JNX05PREUiOmZhbHNlLCJVU0VfU0hBUkVEX01FTU9SWSI6ZmFsc2UsIlVTRV9XQVNJX0NETiI6ZmFsc2V9LCJzdWJzdGl0dXRpb25zIjp7IlBBQ0tBR0VfVE9fSlNfTU9EVUxFX1BBVEgiOiJtYWluLndhc20iLCJQQUNLQUdFX1RPX0pTX1BBQ0tBR0VfTkFNRSI6InRlc3QifX0=", "wants" : [ "$OUTPUT", "$OUTPUT\/bin" diff --git a/README.md b/README.md index 2f41b7a31..03129c3e2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # JavaScriptKit [![Run unit tests](https://github.com/swiftwasm/JavaScriptKit/actions/workflows/test.yml/badge.svg)](https://github.com/swiftwasm/JavaScriptKit/actions/workflows/test.yml) -[![](https://img.shields.io/badge/docc-read_documentation-blue)](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation) +[![Documentation](https://img.shields.io/badge/docc-read_documentation-blue)](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation) Swift framework to interact with JavaScript through WebAssembly. @@ -40,7 +40,85 @@ button.onclick = .object(JSClosure { _ in _ = document.body.appendChild(button) ``` -Check out the [examples](https://github.com/swiftwasm/JavaScriptKit/tree/main/Examples) for more detailed usage. +**Learn more:** [JavaScript Interop Cheat Sheet](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/javascript-interop-cheat-sheet) + +## BridgeJS Plugin + +> **Note:** BridgeJS is experimental. APIs may change in future releases. + +BridgeJS provides easy interoperability between Swift and JavaScript/TypeScript. It enables: + +- **Export Swift to JavaScript** - Expose Swift functions, classes, and types to JavaScript; the plugin also generates TypeScript definitions (`.d.ts`) for the exported API. +- **Import JavaScript into Swift** - Make JavaScript/TypeScript APIs (functions, classes, globals like `document` or `console`) callable from Swift with type-safe bindings. You can declare bindings with macros in Swift or generate them from a TypeScript declaration file (`bridge-js.d.ts`). + +For architecture details, see the [BridgeJS Plugin README](Plugins/BridgeJS/README.md). For package and build setup, see [Setting up BridgeJS](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/setting-up-bridgejs) in the documentation. + +### Exporting Swift to JavaScript + +Mark Swift code with `@JS` to make it callable from JavaScript: + +```swift +import JavaScriptKit + +@JS class Greeter { + @JS var name: String + + @JS init(name: String) { + self.name = name + } + + @JS func greet() -> String { + return "Hello, \(name)!" + } +} +``` + +**JavaScript usage:** +```javascript +const greeter = new exports.Greeter("World"); +console.log(greeter.greet()); // "Hello, World!" +``` + +**Learn more:** [Exporting Swift to JavaScript](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/exporting-swift-to-javascript) + +### Importing JavaScript into Swift + +Declare bindings in Swift with macros such as `@JSFunction`, `@JSClass`, `@JSGetter`, and `@JSSetter`: + +```swift +import JavaScriptKit + +@JSClass struct Document { + @JSFunction func getElementById(_ id: String) throws(JSException) -> HTMLElement + @JSFunction func createElement(_ tagName: String) throws(JSException) -> HTMLElement +} +@JSGetter(from: .global) var document: Document + +@JSClass struct HTMLElement { + @JSGetter var innerText: String + @JSSetter func setInnerText(_ newValue: String) throws(JSException) + @JSFunction func appendChild(_ child: HTMLElement) throws(JSException) +} + +@JS func run() throws(JSException) { + let button = try document.createElement("button") + try button.setInnerText("Click Me") + let container = try document.getElementById("app") + try container.appendChild(button) +} +``` + +You can also generate the same macro-annotated Swift from a TypeScript file (`bridge-js.d.ts`). See [Generating bindings from TypeScript](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/generating-from-typescript) in the documentation. + +**Learn more:** [Importing JavaScript into Swift](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/importing-javascript-into-swift) + +### Try It Online + +Use the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/) to preview what interfaces will be exposed on the Swift/TypeScript sides. + +## Examples + +Check out the [examples](https://github.com/swiftwasm/JavaScriptKit/tree/main/Examples) for more detailed usage patterns. ## Contributing @@ -49,7 +127,3 @@ Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details on ## Sponsoring [Become a gold or platinum sponsor](https://github.com/sponsors/swiftwasm/) and contact maintainers to add your logo on our README on Github with a link to your site. - - - - diff --git a/Runtime/src/closure-heap.ts b/Runtime/src/closure-heap.ts index 269934390..0ec0ba9ac 100644 --- a/Runtime/src/closure-heap.ts +++ b/Runtime/src/closure-heap.ts @@ -10,7 +10,7 @@ export class SwiftClosureDeallocator { "The Swift part of JavaScriptKit was configured to require " + "the availability of JavaScript WeakRefs. Please build " + "with `-Xswiftc -DJAVASCRIPTKIT_WITHOUT_WEAKREFS` to " + - "disable features that use WeakRefs." + "disable features that use WeakRefs.", ); } diff --git a/Runtime/src/find-global.ts b/Runtime/src/find-global.ts index f20afbf34..1530f446e 100644 --- a/Runtime/src/find-global.ts +++ b/Runtime/src/find-global.ts @@ -1,13 +1 @@ -interface GlobalVariable {} -declare const global: GlobalVariable; - -export let globalVariable: any; -if (typeof globalThis !== "undefined") { - globalVariable = globalThis; -} else if (typeof window !== "undefined") { - globalVariable = window; -} else if (typeof global !== "undefined") { - globalVariable = global; -} else if (typeof self !== "undefined") { - globalVariable = self; -} +export const globalVariable: any = globalThis; diff --git a/Runtime/src/index.ts b/Runtime/src/index.ts index 27b52c7da..5d6fe258f 100644 --- a/Runtime/src/index.ts +++ b/Runtime/src/index.ts @@ -7,7 +7,16 @@ import { MAIN_THREAD_TID, } from "./types.js"; import * as JSValue from "./js-value.js"; -import { deserializeError, MainToWorkerMessage, MessageBroker, ResponseMessage, ITCInterface, serializeError, SwiftRuntimeThreadChannel, WorkerToMainMessage } from "./itc.js"; +import { + deserializeError, + MainToWorkerMessage, + MessageBroker, + ResponseMessage, + ITCInterface, + serializeError, + SwiftRuntimeThreadChannel, + WorkerToMainMessage, +} from "./itc.js"; import { decodeObjectRefs } from "./js-value.js"; import { JSObjectSpace } from "./object-heap.js"; export { SwiftRuntimeThreadChannel }; @@ -36,8 +45,8 @@ export class SwiftRuntime { private textEncoder = new TextEncoder(); // Only support utf-8 /** The thread ID of the current thread. */ private tid: number | null; - private getDataView: (() => DataView); - private getUint8Array: (() => Uint8Array); + private getDataView: () => DataView; + private getUint8Array: () => Uint8Array; private wasmMemory: WebAssembly.Memory | null; UnsafeEventLoopYield = UnsafeEventLoopYield; @@ -49,10 +58,14 @@ export class SwiftRuntime { this.tid = null; this.options = options || {}; this.getDataView = () => { - throw new Error("Please call setInstance() before using any JavaScriptKit APIs from Swift."); + throw new Error( + "Please call setInstance() before using any JavaScriptKit APIs from Swift.", + ); }; this.getUint8Array = () => { - throw new Error("Please call setInstance() before using any JavaScriptKit APIs from Swift."); + throw new Error( + "Please call setInstance() before using any JavaScriptKit APIs from Swift.", + ); }; this.wasmMemory = null; } @@ -70,7 +83,10 @@ export class SwiftRuntime { // 1. It may not be available in the global scope if the context is not cross-origin isolated. // 2. The underlying buffer may be still backed by SAB even if the context is not cross-origin // isolated (e.g. localhost on Chrome on Android). - if (Object.getPrototypeOf(wasmMemory.buffer).constructor.name === "SharedArrayBuffer") { + if ( + Object.getPrototypeOf(wasmMemory.buffer).constructor.name === + "SharedArrayBuffer" + ) { // When the wasm memory is backed by a SharedArrayBuffer, growing the memory // doesn't invalidate the data view by setting the byte length to 0. Instead, // the data view points to an old buffer after growing the memory. So we have @@ -105,14 +121,16 @@ export class SwiftRuntime { } this.wasmMemory = wasmMemory; } else { - throw new Error("instance.exports.memory is not a WebAssembly.Memory!?"); + throw new Error( + "instance.exports.memory is not a WebAssembly.Memory!?", + ); } if (typeof (this.exports as any)._start === "function") { throw new Error( `JavaScriptKit supports only WASI reactor ABI. Please make sure you are building with: -Xswiftc -Xclang-linker -Xswiftc -mexec-model=reactor - ` + `, ); } if (this.exports.swjs_library_version() != this.version) { @@ -120,7 +138,7 @@ export class SwiftRuntime { `The versions of JavaScriptKit are incompatible. WebAssembly runtime ${this.exports.swjs_library_version()} != JS runtime ${ this.version - }` + }`, ); } } @@ -159,7 +177,7 @@ export class SwiftRuntime { instance.exports.wasi_thread_start(tid, startArg); } else { throw new Error( - `The WebAssembly module is not built for wasm32-unknown-wasip1-threads target.` + `The WebAssembly module is not built for wasm32-unknown-wasip1-threads target.`, ); } } catch (error) { @@ -190,7 +208,7 @@ export class SwiftRuntime { (features & LibraryFeatures.WeakRefs) != 0; if (librarySupportsWeakRef) { this._closureDeallocator = new SwiftClosureDeallocator( - this.exports + this.exports, ); } return this._closureDeallocator; @@ -200,7 +218,7 @@ export class SwiftRuntime { host_func_id: number, line: number, file: string, - args: any[] + args: any[], ) { const argc = args.length; const argv = this.exports.swjs_prepare_host_function_call(argc); @@ -209,7 +227,15 @@ export class SwiftRuntime { for (let index = 0; index < args.length; index++) { const argument = args[index]; const base = argv + 16 * index; - JSValue.write(argument, base, base + 4, base + 8, false, dataView, memory); + JSValue.write( + argument, + base, + base + 4, + base + 8, + false, + dataView, + memory, + ); } let output: any; // This ref is released by the swjs_call_host_function implementation @@ -220,11 +246,11 @@ export class SwiftRuntime { host_func_id, argv, argc, - callback_func_ref + callback_func_ref, ); if (alreadyReleased) { throw new Error( - `The JSClosure has been already released by Swift side. The closure is created at ${file}:${line} @${host_func_id}` + `The JSClosure has been already released by Swift side. The closure is created at ${file}:${line} @${host_func_id}`, ); } this.exports.swjs_cleanup_host_function_call(argv); @@ -244,10 +270,15 @@ export class SwiftRuntime { let returnValue: ResponseMessage["data"]["response"]; try { // @ts-ignore - const result = itcInterface[message.data.request.method](...message.data.request.parameters); + const result = itcInterface[ + message.data.request.method + ](...message.data.request.parameters); returnValue = { ok: true, value: result }; } catch (error) { - returnValue = { ok: false, error: serializeError(error) }; + returnValue = { + ok: false, + error: serializeError(error), + }; } const responseMessage: ResponseMessage = { type: "response", @@ -256,38 +287,52 @@ export class SwiftRuntime { context: message.data.context, response: returnValue, }, - } + }; try { newBroker.reply(responseMessage); } catch (error) { responseMessage.data.response = { ok: false, - error: serializeError(new TypeError(`Failed to serialize message: ${error}`)) + error: serializeError( + new TypeError( + `Failed to serialize message: ${error}`, + ), + ), }; newBroker.reply(responseMessage); } }, onResponse: (message) => { if (message.data.response.ok) { - const object = this.memory.retain(message.data.response.value.object); - this.exports.swjs_receive_response(object, message.data.context); + const object = this.memory.retain( + message.data.response.value.object, + ); + this.exports.swjs_receive_response( + object, + message.data.context, + ); } else { - const error = deserializeError(message.data.response.error); + const error = deserializeError( + message.data.response.error, + ); const errorObject = this.memory.retain(error); - this.exports.swjs_receive_error(errorObject, message.data.context); + this.exports.swjs_receive_error( + errorObject, + message.data.context, + ); } - } - }) + }, + }); broker = newBroker; return newBroker; - } + }; return { swjs_set_prop: ( ref: ref, name: ref, kind: JSValue.Kind, payload1: number, - payload2: number + payload2: number, ) => { const memory = this.memory; const obj = memory.getObject(ref); @@ -299,7 +344,7 @@ export class SwiftRuntime { ref: ref, name: ref, payload1_ptr: pointer, - payload2_ptr: pointer + payload2_ptr: pointer, ) => { const memory = this.memory; const obj = memory.getObject(ref); @@ -311,7 +356,7 @@ export class SwiftRuntime { payload2_ptr, false, this.getDataView(), - this.memory + this.memory, ); }, @@ -320,7 +365,7 @@ export class SwiftRuntime { index: number, kind: JSValue.Kind, payload1: number, - payload2: number + payload2: number, ) => { const memory = this.memory; const obj = memory.getObject(ref); @@ -331,7 +376,7 @@ export class SwiftRuntime { ref: ref, index: number, payload1_ptr: pointer, - payload2_ptr: pointer + payload2_ptr: pointer, ) => { const obj = this.memory.getObject(ref); const result = obj[index]; @@ -341,7 +386,7 @@ export class SwiftRuntime { payload2_ptr, false, this.getDataView(), - this.memory + this.memory, ); }, @@ -352,22 +397,25 @@ export class SwiftRuntime { this.getDataView().setUint32(bytes_ptr_result, bytes_ptr, true); return bytes.length; }, - swjs_decode_string: ( + swjs_decode_string: // NOTE: TextDecoder can't decode typed arrays backed by SharedArrayBuffer this.options.sharedMemory == true - ? ((bytes_ptr: pointer, length: number) => { - const bytes = this.getUint8Array() - .slice(bytes_ptr, bytes_ptr + length); - const string = this.textDecoder.decode(bytes); - return this.memory.retain(string); - }) - : ((bytes_ptr: pointer, length: number) => { - const bytes = this.getUint8Array() - .subarray(bytes_ptr, bytes_ptr + length); - const string = this.textDecoder.decode(bytes); - return this.memory.retain(string); - }) - ), + ? (bytes_ptr: pointer, length: number) => { + const bytes = this.getUint8Array().slice( + bytes_ptr, + bytes_ptr + length, + ); + const string = this.textDecoder.decode(bytes); + return this.memory.retain(string); + } + : (bytes_ptr: pointer, length: number) => { + const bytes = this.getUint8Array().subarray( + bytes_ptr, + bytes_ptr + length, + ); + const string = this.textDecoder.decode(bytes); + return this.memory.retain(string); + }, swjs_load_string: (ref: ref, buffer: pointer) => { const bytes = this.memory.getObject(ref); this.getUint8Array().set(bytes, buffer); @@ -378,13 +426,18 @@ export class SwiftRuntime { argv: pointer, argc: number, payload1_ptr: pointer, - payload2_ptr: pointer + payload2_ptr: pointer, ) => { const memory = this.memory; const func = memory.getObject(ref); - let result = undefined; + let result: any; try { - const args = JSValue.decodeArray(argv, argc, this.getDataView(), memory); + const args = JSValue.decodeArray( + argv, + argc, + this.getDataView(), + memory, + ); result = func(...args); } catch (error) { return JSValue.writeAndReturnKindBits( @@ -393,7 +446,7 @@ export class SwiftRuntime { payload2_ptr, true, this.getDataView(), - this.memory + this.memory, ); } return JSValue.writeAndReturnKindBits( @@ -402,7 +455,7 @@ export class SwiftRuntime { payload2_ptr, false, this.getDataView(), - this.memory + this.memory, ); }, swjs_call_function_no_catch: ( @@ -410,11 +463,16 @@ export class SwiftRuntime { argv: pointer, argc: number, payload1_ptr: pointer, - payload2_ptr: pointer + payload2_ptr: pointer, ) => { const memory = this.memory; const func = memory.getObject(ref); - const args = JSValue.decodeArray(argv, argc, this.getDataView(), memory); + const args = JSValue.decodeArray( + argv, + argc, + this.getDataView(), + memory, + ); const result = func(...args); return JSValue.writeAndReturnKindBits( result, @@ -422,7 +480,7 @@ export class SwiftRuntime { payload2_ptr, false, this.getDataView(), - this.memory + this.memory, ); }, @@ -432,14 +490,19 @@ export class SwiftRuntime { argv: pointer, argc: number, payload1_ptr: pointer, - payload2_ptr: pointer + payload2_ptr: pointer, ) => { const memory = this.memory; const obj = memory.getObject(obj_ref); const func = memory.getObject(func_ref); let result: any; try { - const args = JSValue.decodeArray(argv, argc, this.getDataView(), memory); + const args = JSValue.decodeArray( + argv, + argc, + this.getDataView(), + memory, + ); result = func.apply(obj, args); } catch (error) { return JSValue.writeAndReturnKindBits( @@ -448,7 +511,7 @@ export class SwiftRuntime { payload2_ptr, true, this.getDataView(), - this.memory + this.memory, ); } return JSValue.writeAndReturnKindBits( @@ -457,7 +520,7 @@ export class SwiftRuntime { payload2_ptr, false, this.getDataView(), - this.memory + this.memory, ); }, swjs_call_function_with_this_no_catch: ( @@ -466,28 +529,37 @@ export class SwiftRuntime { argv: pointer, argc: number, payload1_ptr: pointer, - payload2_ptr: pointer + payload2_ptr: pointer, ) => { const memory = this.memory; const obj = memory.getObject(obj_ref); const func = memory.getObject(func_ref); - let result = undefined; - const args = JSValue.decodeArray(argv, argc, this.getDataView(), memory); - result = func.apply(obj, args); + const args = JSValue.decodeArray( + argv, + argc, + this.getDataView(), + memory, + ); + const result = func.apply(obj, args); return JSValue.writeAndReturnKindBits( result, payload1_ptr, payload2_ptr, false, this.getDataView(), - this.memory + this.memory, ); }, swjs_call_new: (ref: ref, argv: pointer, argc: number) => { const memory = this.memory; const constructor = memory.getObject(ref); - const args = JSValue.decodeArray(argv, argc, this.getDataView(), memory); + const args = JSValue.decodeArray( + argv, + argc, + this.getDataView(), + memory, + ); const instance = new constructor(...args); return this.memory.retain(instance); }, @@ -497,13 +569,18 @@ export class SwiftRuntime { argc: number, exception_kind_ptr: pointer, exception_payload1_ptr: pointer, - exception_payload2_ptr: pointer + exception_payload2_ptr: pointer, ) => { let memory = this.memory; const constructor = memory.getObject(ref); let result: any; try { - const args = JSValue.decodeArray(argv, argc, this.getDataView(), memory); + const args = JSValue.decodeArray( + argv, + argc, + this.getDataView(), + memory, + ); result = new constructor(...args); } catch (error) { JSValue.write( @@ -513,7 +590,7 @@ export class SwiftRuntime { exception_payload2_ptr, true, this.getDataView(), - this.memory + this.memory, ); return -1; } @@ -525,7 +602,7 @@ export class SwiftRuntime { exception_payload2_ptr, false, this.getDataView(), - memory + memory, ); return memory.retain(result); }, @@ -547,7 +624,7 @@ export class SwiftRuntime { swjs_create_function: ( host_func_id: number, line: number, - file: ref + file: ref, ) => { const fileString = this.memory.getObject(file) as string; const func = (...args: any[]) => @@ -560,7 +637,7 @@ export class SwiftRuntime { swjs_create_oneshot_function: ( host_func_id: number, line: number, - file: ref + file: ref, ) => { const fileString = this.memory.getObject(file) as string; const func = (...args: any[]) => @@ -569,13 +646,30 @@ export class SwiftRuntime { return func_ref; }, - swjs_create_typed_array: ( + swjs_create_typed_array: < + T extends + | Int8Array + | Uint8Array + | Int16Array + | Uint16Array + | Int32Array + | Uint32Array + | BigInt64Array + | BigUint64Array + | Float32Array + | Float64Array + | Uint8ClampedArray, + >( constructor_ref: ref, elementsPtr: pointer, - length: number + length: number, ) => { type TypedArrayConstructor = { - new (buffer: ArrayBuffer, byteOffset: number, length: number): T; + new ( + buffer: ArrayBuffer, + byteOffset: number, + length: number, + ): T; new (): T; }; const ArrayType: TypedArrayConstructor = @@ -592,13 +686,15 @@ export class SwiftRuntime { const array = new ArrayType( this.wasmMemory!.buffer, elementsPtr, - length + length, ); // Call `.slice()` to copy the memory return this.memory.retain(array.slice()); }, - swjs_create_object: () => { return this.memory.retain({}); }, + swjs_create_object: () => { + return this.memory.retain({}); + }, swjs_load_typed_array: (ref: ref, buffer: pointer) => { const memory = this.memory; @@ -613,7 +709,9 @@ export class SwiftRuntime { swjs_release_remote: (tid: number, ref: ref) => { if (!this.options.threadChannel) { - throw new Error("threadChannel is not set in options given to SwiftRuntime. Please set it to release objects on remote threads."); + throw new Error( + "threadChannel is not set in options given to SwiftRuntime. Please set it to release objects on remote threads.", + ); } const broker = getMessageBroker(this.options.threadChannel); broker.request({ @@ -625,20 +723,22 @@ export class SwiftRuntime { request: { method: "release", parameters: [ref], - } - } - }) + }, + }, + }); }, swjs_i64_to_bigint: (value: bigint, signed: number) => { return this.memory.retain( - signed ? value : BigInt.asUintN(64, value) + signed ? value : BigInt.asUintN(64, value), ); }, swjs_bigint_to_i64: (ref: ref, signed: number) => { const object = this.memory.getObject(ref); if (typeof object !== "bigint") { - throw new Error(`Expected a BigInt, but got ${typeof object}`); + throw new Error( + `Expected a BigInt, but got ${typeof object}`, + ); } if (signed) { return object; @@ -649,44 +749,61 @@ export class SwiftRuntime { return BigInt.asIntN(64, object); } }, - swjs_i64_to_bigint_slow: (lower: number, upper: number, signed: number) => { + swjs_i64_to_bigint_slow: ( + lower: number, + upper: number, + signed: number, + ) => { const value = BigInt.asUintN(32, BigInt(lower)) + (BigInt.asUintN(32, BigInt(upper)) << BigInt(32)); return this.memory.retain( - signed ? BigInt.asIntN(64, value) : BigInt.asUintN(64, value) + signed + ? BigInt.asIntN(64, value) + : BigInt.asUintN(64, value), ); }, swjs_unsafe_event_loop_yield: () => { throw new UnsafeEventLoopYield(); }, swjs_send_job_to_main_thread: (unowned_job: number) => { - this.postMessageToMainThread({ type: "job", data: unowned_job }); + this.postMessageToMainThread({ + type: "job", + data: unowned_job, + }); }, swjs_listen_message_from_main_thread: () => { const threadChannel = this.options.threadChannel; - if (!(threadChannel && "listenMessageFromMainThread" in threadChannel)) { + if ( + !( + threadChannel && + "listenMessageFromMainThread" in threadChannel + ) + ) { throw new Error( - "listenMessageFromMainThread is not set in options given to SwiftRuntime. Please set it to listen to wake events from the main thread." + "listenMessageFromMainThread is not set in options given to SwiftRuntime. Please set it to listen to wake events from the main thread.", ); } const broker = getMessageBroker(threadChannel); threadChannel.listenMessageFromMainThread((message) => { switch (message.type) { - case "wake": - this.exports.swjs_wake_worker_thread(); - break; - case "request": { - broker.onReceivingRequest(message); - break; - } - case "response": { - broker.onReceivingResponse(message); - break; - } - default: - const unknownMessage: never = message; - throw new Error(`Unknown message type: ${unknownMessage}`); + case "wake": + this.exports.swjs_wake_worker_thread(); + break; + case "request": { + broker.onReceivingRequest(message); + break; + } + case "response": { + broker.onReceivingResponse(message); + break; + } + default: { + const unknownMessage: never = message; + throw new Error( + `Unknown message type: ${unknownMessage}`, + ); + } } }); }, @@ -695,17 +812,23 @@ export class SwiftRuntime { }, swjs_listen_message_from_worker_thread: (tid: number) => { const threadChannel = this.options.threadChannel; - if (!(threadChannel && "listenMessageFromWorkerThread" in threadChannel)) { + if ( + !( + threadChannel && + "listenMessageFromWorkerThread" in threadChannel + ) + ) { throw new Error( - "listenMessageFromWorkerThread is not set in options given to SwiftRuntime. Please set it to listen to jobs from worker threads." + "listenMessageFromWorkerThread is not set in options given to SwiftRuntime. Please set it to listen to jobs from worker threads.", ); } const broker = getMessageBroker(threadChannel); - threadChannel.listenMessageFromWorkerThread( - tid, (message) => { - switch (message.type) { + threadChannel.listenMessageFromWorkerThread(tid, (message) => { + switch (message.type) { case "job": - this.exports.swjs_enqueue_main_job_from_worker(message.data); + this.exports.swjs_enqueue_main_job_from_worker( + message.data, + ); break; case "request": { broker.onReceivingRequest(message); @@ -715,12 +838,14 @@ export class SwiftRuntime { broker.onReceivingResponse(message); break; } - default: + default: { const unknownMessage: never = message; - throw new Error(`Unknown message type: ${unknownMessage}`); + throw new Error( + `Unknown message type: ${unknownMessage}`, + ); } - }, - ); + } + }); }, swjs_terminate_worker_thread: (tid: number) => { const threadChannel = this.options.threadChannel; @@ -740,10 +865,16 @@ export class SwiftRuntime { sending_context: pointer, ) => { if (!this.options.threadChannel) { - throw new Error("threadChannel is not set in options given to SwiftRuntime. Please set it to request transferring objects."); + throw new Error( + "threadChannel is not set in options given to SwiftRuntime. Please set it to request transferring objects.", + ); } const broker = getMessageBroker(this.options.threadChannel); - const transferringObjects = decodeObjectRefs(transferring_objects, transferring_objects_count, this.getDataView()); + const transferringObjects = decodeObjectRefs( + transferring_objects, + transferring_objects_count, + this.getDataView(), + ); broker.request({ type: "request", data: { @@ -752,10 +883,14 @@ export class SwiftRuntime { context: sending_context, request: { method: "send", - parameters: [sending_object, transferringObjects, sending_context], - } - } - }) + parameters: [ + sending_object, + transferringObjects, + sending_context, + ], + }, + }, + }); }, swjs_request_sending_objects: ( sending_objects: pointer, @@ -766,12 +901,22 @@ export class SwiftRuntime { sending_context: pointer, ) => { if (!this.options.threadChannel) { - throw new Error("threadChannel is not set in options given to SwiftRuntime. Please set it to request transferring objects."); + throw new Error( + "threadChannel is not set in options given to SwiftRuntime. Please set it to request transferring objects.", + ); } const broker = getMessageBroker(this.options.threadChannel); const dataView = this.getDataView(); - const sendingObjects = decodeObjectRefs(sending_objects, sending_objects_count, dataView); - const transferringObjects = decodeObjectRefs(transferring_objects, transferring_objects_count, dataView); + const sendingObjects = decodeObjectRefs( + sending_objects, + sending_objects_count, + dataView, + ); + const transferringObjects = decodeObjectRefs( + transferring_objects, + transferring_objects_count, + dataView, + ); broker.request({ type: "request", data: { @@ -780,29 +925,40 @@ export class SwiftRuntime { context: sending_context, request: { method: "sendObjects", - parameters: [sendingObjects, transferringObjects, sending_context], - } - } - }) + parameters: [ + sendingObjects, + transferringObjects, + sending_context, + ], + }, + }, + }); }, }; } - private postMessageToMainThread(message: WorkerToMainMessage, transfer: any[] = []) { + private postMessageToMainThread( + message: WorkerToMainMessage, + transfer: any[] = [], + ) { const threadChannel = this.options.threadChannel; if (!(threadChannel && "postMessageToMainThread" in threadChannel)) { throw new Error( - "postMessageToMainThread is not set in options given to SwiftRuntime. Please set it to send messages to the main thread." + "postMessageToMainThread is not set in options given to SwiftRuntime. Please set it to send messages to the main thread.", ); } threadChannel.postMessageToMainThread(message, transfer); } - private postMessageToWorkerThread(tid: number, message: MainToWorkerMessage, transfer: any[] = []) { + private postMessageToWorkerThread( + tid: number, + message: MainToWorkerMessage, + transfer: any[] = [], + ) { const threadChannel = this.options.threadChannel; if (!(threadChannel && "postMessageToWorkerThread" in threadChannel)) { throw new Error( - "postMessageToWorkerThread is not set in options given to SwiftRuntime. Please set it to send messages to worker threads." + "postMessageToWorkerThread is not set in options given to SwiftRuntime. Please set it to send messages to worker threads.", ); } threadChannel.postMessageToWorkerThread(tid, message, transfer); diff --git a/Runtime/src/itc.ts b/Runtime/src/itc.ts index 08b420640..9fadff54a 100644 --- a/Runtime/src/itc.ts +++ b/Runtime/src/itc.ts @@ -39,19 +39,24 @@ import { JSObjectSpace as JSObjectSpace } from "./object-heap.js"; */ export type SwiftRuntimeThreadChannel = | { - /** - * This function is used to send messages from the worker thread to the main thread. - * The message submitted by this function is expected to be listened by `listenMessageFromWorkerThread`. - * @param message The message to be sent to the main thread. - * @param transfer The array of objects to be transferred to the main thread. - */ - postMessageToMainThread: (message: WorkerToMainMessage, transfer: any[]) => void; + /** + * This function is used to send messages from the worker thread to the main thread. + * The message submitted by this function is expected to be listened by `listenMessageFromWorkerThread`. + * @param message The message to be sent to the main thread. + * @param transfer The array of objects to be transferred to the main thread. + */ + postMessageToMainThread: ( + message: WorkerToMainMessage, + transfer: any[], + ) => void; /** * This function is expected to be set in the worker thread and should listen * to messages from the main thread sent by `postMessageToWorkerThread`. * @param listener The listener function to be called when a message is received from the main thread. */ - listenMessageFromMainThread: (listener: (message: MainToWorkerMessage) => void) => void; + listenMessageFromMainThread: ( + listener: (message: MainToWorkerMessage) => void, + ) => void; } | { /** @@ -61,7 +66,11 @@ export type SwiftRuntimeThreadChannel = * @param message The message to be sent to the worker thread. * @param transfer The array of objects to be transferred to the worker thread. */ - postMessageToWorkerThread: (tid: number, message: MainToWorkerMessage, transfer: any[]) => void; + postMessageToWorkerThread: ( + tid: number, + message: MainToWorkerMessage, + transfer: any[], + ) => void; /** * This function is expected to be set in the main thread and should listen * to messages sent by `postMessageToMainThread` from the worker thread. @@ -70,7 +79,7 @@ export type SwiftRuntimeThreadChannel = */ listenMessageFromWorkerThread: ( tid: number, - listener: (message: WorkerToMainMessage) => void + listener: (message: WorkerToMainMessage) => void, ) => void; /** @@ -81,23 +90,34 @@ export type SwiftRuntimeThreadChannel = terminateWorkerThread?: (tid: number) => void; }; - export class ITCInterface { constructor(private memory: JSObjectSpace) {} - send(sendingObject: ref, transferringObjects: ref[], sendingContext: pointer): { object: any, sendingContext: pointer, transfer: Transferable[] } { + send( + sendingObject: ref, + transferringObjects: ref[], + sendingContext: pointer, + ): { object: any; sendingContext: pointer; transfer: Transferable[] } { const object = this.memory.getObject(sendingObject); - const transfer = transferringObjects.map(ref => this.memory.getObject(ref)); + const transfer = transferringObjects.map((ref) => + this.memory.getObject(ref), + ); return { object, sendingContext, transfer }; } - sendObjects(sendingObjects: ref[], transferringObjects: ref[], sendingContext: pointer): { object: any[], sendingContext: pointer, transfer: Transferable[] } { - const objects = sendingObjects.map(ref => this.memory.getObject(ref)); - const transfer = transferringObjects.map(ref => this.memory.getObject(ref)); + sendObjects( + sendingObjects: ref[], + transferringObjects: ref[], + sendingContext: pointer, + ): { object: any[]; sendingContext: pointer; transfer: Transferable[] } { + const objects = sendingObjects.map((ref) => this.memory.getObject(ref)); + const transfer = transferringObjects.map((ref) => + this.memory.getObject(ref), + ); return { object: objects, sendingContext, transfer }; } - release(objectRef: ref): { object: undefined, transfer: Transferable[] } { + release(objectRef: ref): { object: undefined; transfer: Transferable[] } { this.memory.release(objectRef); return { object: undefined, transfer: [] }; } @@ -105,16 +125,18 @@ export class ITCInterface { type AllRequests> = { [K in keyof Interface]: { - method: K, - parameters: Parameters, - } -} + method: K; + parameters: Parameters; + }; +}; -type ITCRequest> = AllRequests[keyof AllRequests]; +type ITCRequest> = + AllRequests[keyof AllRequests]; type AllResponses> = { - [K in keyof Interface]: ReturnType -} -type ITCResponse> = AllResponses[keyof AllResponses]; + [K in keyof Interface]: ReturnType; +}; +type ITCResponse> = + AllResponses[keyof AllResponses]; export type RequestMessage = { type: "request"; @@ -127,10 +149,12 @@ export type RequestMessage = { context: pointer; /** The request content */ request: ITCRequest; - } -} + }; +}; -type SerializedError = { isError: true; value: Error } | { isError: false; value: unknown } +type SerializedError = + | { isError: true; value: Error } + | { isError: false; value: unknown }; export type ResponseMessage = { type: "response"; @@ -140,36 +164,42 @@ export type ResponseMessage = { /** The context pointer of the request */ context: pointer; /** The response content */ - response: { - ok: true, - value: ITCResponse; - } | { - ok: false, - error: SerializedError; - }; - } -} + response: + | { + ok: true; + value: ITCResponse; + } + | { + ok: false; + error: SerializedError; + }; + }; +}; -export type MainToWorkerMessage = { - type: "wake"; -} | RequestMessage | ResponseMessage; - -export type WorkerToMainMessage = { - type: "job"; - data: number; -} | RequestMessage | ResponseMessage; +export type MainToWorkerMessage = + | { + type: "wake"; + } + | RequestMessage + | ResponseMessage; +export type WorkerToMainMessage = + | { + type: "job"; + data: number; + } + | RequestMessage + | ResponseMessage; export class MessageBroker { constructor( private selfTid: number, private threadChannel: SwiftRuntimeThreadChannel, private handlers: { - onRequest: (message: RequestMessage) => void, - onResponse: (message: ResponseMessage) => void, - } - ) { - } + onRequest: (message: RequestMessage) => void; + onResponse: (message: ResponseMessage) => void; + }, + ) {} request(message: RequestMessage) { if (message.data.targetTid == this.selfTid) { @@ -177,7 +207,11 @@ export class MessageBroker { this.handlers.onRequest(message); } else if ("postMessageToWorkerThread" in this.threadChannel) { // The request is for another worker thread sent from the main thread - this.threadChannel.postMessageToWorkerThread(message.data.targetTid, message, []); + this.threadChannel.postMessageToWorkerThread( + message.data.targetTid, + message, + [], + ); } else if ("postMessageToMainThread" in this.threadChannel) { // The request is for other worker threads or the main thread sent from a worker thread this.threadChannel.postMessageToMainThread(message, []); @@ -192,10 +226,16 @@ export class MessageBroker { this.handlers.onResponse(message); return; } - const transfer = message.data.response.ok ? message.data.response.value.transfer : []; + const transfer = message.data.response.ok + ? message.data.response.value.transfer + : []; if ("postMessageToWorkerThread" in this.threadChannel) { // The response is for another worker thread sent from the main thread - this.threadChannel.postMessageToWorkerThread(message.data.sourceTid, message, transfer); + this.threadChannel.postMessageToWorkerThread( + message.data.sourceTid, + message, + transfer, + ); } else if ("postMessageToMainThread" in this.threadChannel) { // The response is for other worker threads or the main thread sent from a worker thread this.threadChannel.postMessageToMainThread(message, transfer); @@ -208,9 +248,13 @@ export class MessageBroker { if (message.data.targetTid == this.selfTid) { this.handlers.onRequest(message); } else if ("postMessageToWorkerThread" in this.threadChannel) { - // Receive a request from a worker thread to other worker on main thread. + // Receive a request from a worker thread to other worker on main thread. // Proxy the request to the target worker thread. - this.threadChannel.postMessageToWorkerThread(message.data.targetTid, message, []); + this.threadChannel.postMessageToWorkerThread( + message.data.targetTid, + message, + [], + ); } else if ("postMessageToMainThread" in this.threadChannel) { // A worker thread won't receive a request for other worker threads throw new Error("unreachable"); @@ -223,8 +267,14 @@ export class MessageBroker { } else if ("postMessageToWorkerThread" in this.threadChannel) { // Receive a response from a worker thread to other worker on main thread. // Proxy the response to the target worker thread. - const transfer = message.data.response.ok ? message.data.response.value.transfer : []; - this.threadChannel.postMessageToWorkerThread(message.data.sourceTid, message, transfer); + const transfer = message.data.response.ok + ? message.data.response.value.transfer + : []; + this.threadChannel.postMessageToWorkerThread( + message.data.sourceTid, + message, + transfer, + ); } else if ("postMessageToMainThread" in this.threadChannel) { // A worker thread won't receive a response for other worker threads throw new Error("unreachable"); @@ -234,7 +284,14 @@ export class MessageBroker { export function serializeError(error: unknown): SerializedError { if (error instanceof Error) { - return { isError: true, value: { message: error.message, name: error.name, stack: error.stack } }; + return { + isError: true, + value: { + message: error.message, + name: error.name, + stack: error.stack, + }, + }; } return { isError: false, value: error }; } diff --git a/Runtime/src/js-value.ts b/Runtime/src/js-value.ts index b23f39d87..b044e5cbe 100644 --- a/Runtime/src/js-value.ts +++ b/Runtime/src/js-value.ts @@ -1,5 +1,10 @@ import { JSObjectSpace } from "./object-heap.js"; -import { assertNever, JavaScriptValueKindAndFlags, pointer, ref } from "./types.js"; +import { + assertNever, + JavaScriptValueKindAndFlags, + pointer, + ref, +} from "./types.js"; export const enum Kind { Boolean = 0, @@ -8,7 +13,6 @@ export const enum Kind { Object = 3, Null = 4, Undefined = 5, - Function = 6, Symbol = 7, BigInt = 8, } @@ -17,7 +21,7 @@ export const decode = ( kind: Kind, payload1: number, payload2: number, - objectSpace: JSObjectSpace + objectSpace: JSObjectSpace, ) => { switch (kind) { case Kind.Boolean: @@ -27,12 +31,12 @@ export const decode = ( case 1: return true; } + // falls through case Kind.Number: return payload2; case Kind.String: case Kind.Object: - case Kind.Function: case Kind.Symbol: case Kind.BigInt: return objectSpace.getObject(payload1); @@ -50,7 +54,12 @@ export const decode = ( // Note: // `decodeValues` assumes that the size of RawJSValue is 16. -export const decodeArray = (ptr: pointer, length: number, memory: DataView, objectSpace: JSObjectSpace) => { +export const decodeArray = ( + ptr: pointer, + length: number, + memory: DataView, + objectSpace: JSObjectSpace, +) => { // fast path for empty array if (length === 0) { return []; @@ -78,7 +87,7 @@ export const write = ( payload2_ptr: pointer, is_exception: boolean, memory: DataView, - objectSpace: JSObjectSpace + objectSpace: JSObjectSpace, ) => { const kind = writeAndReturnKindBits( value, @@ -86,7 +95,7 @@ export const write = ( payload2_ptr, is_exception, memory, - objectSpace + objectSpace, ); memory.setUint32(kind_ptr, kind, true); }; @@ -97,7 +106,7 @@ export const writeAndReturnKindBits = ( payload2_ptr: pointer, is_exception: boolean, memory: DataView, - objectSpace: JSObjectSpace + objectSpace: JSObjectSpace, ): JavaScriptValueKindAndFlags => { const exceptionBit = (is_exception ? 1 : 0) << 31; if (value === null) { @@ -129,7 +138,7 @@ export const writeAndReturnKindBits = ( return writeRef(Kind.Object); } case "function": { - return writeRef(Kind.Function); + return writeRef(Kind.Object); } case "symbol": { return writeRef(Kind.Symbol); @@ -143,7 +152,11 @@ export const writeAndReturnKindBits = ( throw new Error("Unreachable"); }; -export function decodeObjectRefs(ptr: pointer, length: number, memory: DataView): ref[] { +export function decodeObjectRefs( + ptr: pointer, + length: number, + memory: DataView, +): ref[] { const result: ref[] = new Array(length); for (let i = 0; i < length; i++) { result[i] = memory.getUint32(ptr + 4 * i, true); diff --git a/Runtime/src/object-heap.ts b/Runtime/src/object-heap.ts index b90fc4eff..ba9cf8021 100644 --- a/Runtime/src/object-heap.ts +++ b/Runtime/src/object-heap.ts @@ -51,7 +51,7 @@ export class JSObjectSpace { const value = this._heapValueById.get(ref); if (value === undefined) { throw new ReferenceError( - "Attempted to read invalid reference " + ref + "Attempted to read invalid reference " + ref, ); } return value; diff --git a/Runtime/src/types.ts b/Runtime/src/types.ts index b8345cdfa..b39e949b2 100644 --- a/Runtime/src/types.ts +++ b/Runtime/src/types.ts @@ -13,7 +13,7 @@ export interface ExportedFunctions { host_func_id: number, argv: pointer, argc: number, - callback_func_ref: ref + callback_func_ref: ref, ): bool; swjs_free_host_function(host_func_id: number): void; diff --git a/Sources/BridgeJSMacros b/Sources/BridgeJSMacros new file mode 120000 index 000000000..2d3d8a4ab --- /dev/null +++ b/Sources/BridgeJSMacros @@ -0,0 +1 @@ +../Plugins/BridgeJS/Sources/BridgeJSMacros \ No newline at end of file diff --git a/Sources/BridgeJSTool/BridgeJSUtilities b/Sources/BridgeJSTool/BridgeJSUtilities new file mode 120000 index 000000000..75db3bd99 --- /dev/null +++ b/Sources/BridgeJSTool/BridgeJSUtilities @@ -0,0 +1 @@ +../../Plugins/BridgeJS/Sources/BridgeJSUtilities \ No newline at end of file diff --git a/Sources/BridgeJSTool/TS2Skeleton b/Sources/BridgeJSTool/TS2Skeleton deleted file mode 120000 index c41c12804..000000000 --- a/Sources/BridgeJSTool/TS2Skeleton +++ /dev/null @@ -1 +0,0 @@ -../../Plugins/BridgeJS/Sources/TS2Skeleton \ No newline at end of file diff --git a/Sources/BridgeJSTool/TS2Swift b/Sources/BridgeJSTool/TS2Swift new file mode 120000 index 000000000..6d9b4332e --- /dev/null +++ b/Sources/BridgeJSTool/TS2Swift @@ -0,0 +1 @@ +../../Plugins/BridgeJS/Sources/TS2Swift \ No newline at end of file diff --git a/Sources/JavaScriptBigIntSupport/Int64+I64.swift b/Sources/JavaScriptBigIntSupport/Int64+I64.swift index e361e72e9..13ea7b92e 100644 --- a/Sources/JavaScriptBigIntSupport/Int64+I64.swift +++ b/Sources/JavaScriptBigIntSupport/Int64+I64.swift @@ -1,13 +1,13 @@ import JavaScriptKit extension UInt64: JavaScriptKit.ConvertibleToJSValue, JavaScriptKit.TypedArrayElement { - public static var typedArrayClass: JSFunction { JSObject.global.BigUint64Array.function! } + public static var typedArrayClass: JSObject { JSObject.global.BigUint64Array.object! } public var jsValue: JSValue { .bigInt(JSBigInt(unsigned: self)) } } extension Int64: JavaScriptKit.ConvertibleToJSValue, JavaScriptKit.TypedArrayElement { - public static var typedArrayClass: JSFunction { JSObject.global.BigInt64Array.function! } + public static var typedArrayClass: JSObject { JSObject.global.BigInt64Array.object! } public var jsValue: JSValue { .bigInt(JSBigInt(self)) } } diff --git a/Sources/JavaScriptEventLoop/JSSending.swift b/Sources/JavaScriptEventLoop/JSSending.swift index 3408b232f..7a3750c15 100644 --- a/Sources/JavaScriptEventLoop/JSSending.swift +++ b/Sources/JavaScriptEventLoop/JSSending.swift @@ -23,7 +23,7 @@ import Synchronization /// /// ```swift /// // Transfer an object to another thread -/// let buffer = JSObject.global.Uint8Array.function!.new(100).buffer.object! +/// let buffer = JSObject.global.Uint8Array.object!.new(100).buffer.object! /// let transferring = JSSending.transfer(buffer) /// /// // Receive the object on a worker thread @@ -34,7 +34,7 @@ import Synchronization /// } /// /// // Clone an object for use in another thread -/// let object = JSObject.global.Object.function!.new() +/// let object = JSObject.global.Object.object!.new() /// object["test"] = "Hello, World!" /// let cloning = JSSending(object) /// @@ -136,7 +136,7 @@ extension JSSending where T == JSObject { /// ## Example /// /// ```swift - /// let buffer = JSObject.global.Uint8Array.function!.new(100).buffer.object! + /// let buffer = JSObject.global.Uint8Array.object!.new(100).buffer.object! /// let transferring = JSSending.transfer(buffer) /// /// // After transfer, the original buffer is neutered @@ -167,7 +167,7 @@ extension JSSending where T == JSObject { /// ## Example /// /// ```swift - /// let object = JSObject.global.Object.function!.new() + /// let object = JSObject.global.Object.object!.new() /// object["test"] = "Hello, World!" /// let cloning = JSSending(object) /// @@ -212,7 +212,7 @@ extension JSSending { /// ## Example - Cloning /// /// ```swift - /// let data = JSObject.global.Object.function!.new() + /// let data = JSObject.global.Object.object!.new() /// data["value"] = 42 /// let cloning = JSSending(data) /// diff --git a/Sources/JavaScriptEventLoop/JavaScriptEventLoop+ExecutorFactory.swift b/Sources/JavaScriptEventLoop/JavaScriptEventLoop+ExecutorFactory.swift index ed60eae76..7de4cb74a 100644 --- a/Sources/JavaScriptEventLoop/JavaScriptEventLoop+ExecutorFactory.swift +++ b/Sources/JavaScriptEventLoop/JavaScriptEventLoop+ExecutorFactory.swift @@ -4,14 +4,19 @@ // See: https://github.com/swiftlang/swift/pull/80266 // See: https://forums.swift.org/t/pitch-2-custom-main-and-global-executors/78437 +#if compiler(>=6.3) +@_spi(ExperimentalCustomExecutors) import _Concurrency +#else import _Concurrency +#endif import _CJavaScriptKit -#if compiler(>=6.2) +#if compiler(>=6.3) // 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,22 +32,38 @@ extension JavaScriptEventLoop: MainExecutor { extension JavaScriptEventLoop: TaskExecutor {} @available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999, *) -extension JavaScriptEventLoop: SchedulableExecutor { +@_spi(ExperimentalCustomExecutors) +extension JavaScriptEventLoop: SchedulingExecutor { public func enqueue( _ job: consuming ExecutorJob, after delay: C.Duration, tolerance: C.Duration?, clock: C ) { - let milliseconds = Self.delayInMilliseconds(from: delay, clock: clock) + let duration: Duration + // Handle clocks we know + if let _ = clock as? ContinuousClock { + duration = delay as! ContinuousClock.Duration + } else if let _ = clock as? SuspendingClock { + duration = delay as! SuspendingClock.Duration + } else { + // Hand-off the scheduling work to Clock implementation for unknown clocks + clock.enqueue( + job, + on: self, + at: clock.now.advanced(by: delay), + tolerance: tolerance + ) + return + } + let milliseconds = Self.delayInMilliseconds(from: duration) self.enqueue( UnownedJob(job), withDelay: milliseconds ) } - private static func delayInMilliseconds(from duration: C.Duration, clock: C) -> Double { - let swiftDuration = clock.convert(from: duration)! + private static func delayInMilliseconds(from swiftDuration: Duration) -> Double { let (seconds, attoseconds) = swiftDuration.components return Double(seconds) * 1_000 + (Double(attoseconds) / 1_000_000_000_000_000) } @@ -50,9 +71,10 @@ extension JavaScriptEventLoop: SchedulableExecutor { // 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, SchedulableExecutor, MainExecutor, SerialExecutor { + final class CurrentThread: TaskExecutor, SchedulingExecutor, MainExecutor, SerialExecutor { func checkIsolated() {} func enqueue(_ job: consuming ExecutorJob) { @@ -89,4 +111,4 @@ extension JavaScriptEventLoop: ExecutorFactory { } } -#endif // compiler(>=6.2) +#endif // compiler(>=6.3) diff --git a/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift b/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift index 1cb90f8d8..aebc90d65 100644 --- a/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift +++ b/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift @@ -1,5 +1,9 @@ import JavaScriptKit +#if compiler(>=6.3) +@_spi(ExperimentalCustomExecutors) import _Concurrency +#else import _Concurrency +#endif import _CJavaScriptEventLoop import _CJavaScriptKit @@ -82,7 +86,7 @@ public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable { let promise = JSPromise(resolver: { resolver -> Void in resolver(.success(.undefined)) }) - let setTimeout = JSObject.global.setTimeout.function! + let setTimeout = JSObject.global.setTimeout.object! let eventLoop = JavaScriptEventLoop( queueTask: { job in // TODO(katei): Should prefer `queueMicrotask` if available? @@ -119,9 +123,9 @@ public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable { private static func installGlobalExecutorIsolated() { guard !didInstallGlobalExecutor else { return } didInstallGlobalExecutor = true - #if compiler(>=6.2) + #if compiler(>=6.3) if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999, *) { - // For Swift 6.2 and above, we can use the new `ExecutorFactory` API + // For Swift 6.3 and above, we can use the new `ExecutorFactory` API _Concurrency._createExecutors(factory: JavaScriptEventLoop.self) } #else diff --git a/Sources/JavaScriptEventLoop/WebWorkerTaskExecutor.swift b/Sources/JavaScriptEventLoop/WebWorkerTaskExecutor.swift index 992b6090a..b827ad980 100644 --- a/Sources/JavaScriptEventLoop/WebWorkerTaskExecutor.swift +++ b/Sources/JavaScriptEventLoop/WebWorkerTaskExecutor.swift @@ -34,7 +34,7 @@ import WASILibc /// /// ```swift /// // Create and transfer an object to a worker thread -/// let buffer = JSObject.global.ArrayBuffer.function!.new(1024).object! +/// let buffer = JSObject.global.ArrayBuffer.object!.new(1024).object! /// let transferring = JSSending.transfer(buffer) /// /// let task = Task(executorPreference: executor) { @@ -451,7 +451,7 @@ public final class WebWorkerTaskExecutor: TaskExecutor { swjs_listen_message_from_worker_thread(tid) } #else - fatalError("Unsupported platform") + fatalError("Unsupported platform. WebWorkerTaskExecutor requires Swift SDK for wasip1-threads target.") #endif } diff --git a/Sources/JavaScriptKit/BasicObjects/JSArray.swift b/Sources/JavaScriptKit/BasicObjects/JSArray.swift index fad602465..9f24f48fd 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSArray.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSArray.swift @@ -2,8 +2,8 @@ /// class](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) /// that exposes its properties in a type-safe and Swifty way. public class JSArray: JSBridgedClass { - public static var constructor: JSFunction? { _constructor.wrappedValue } - private static let _constructor = LazyThreadLocal(initialize: { JSObject.global.Array.function }) + public static var constructor: JSObject? { _constructor.wrappedValue } + private static let _constructor = LazyThreadLocal(initialize: { JSObject.global.Array.object }) static func isArray(_ object: JSObject) -> Bool { constructor!.isArray!(object).boolean! @@ -19,7 +19,7 @@ public class JSArray: JSBridgedClass { /// Construct a `JSArray` from Array `JSObject`. /// Return `nil` if the object is not an Array. /// - /// - Parameter object: A `JSObject` expected to be a JavaScript Array + /// - Parameter jsObject: A `JSObject` expected to be a JavaScript Array public convenience init?(_ jsObject: JSObject) { guard Self.isArray(jsObject) else { return nil } self.init(unsafelyWrapping: jsObject) diff --git a/Sources/JavaScriptKit/BasicObjects/JSDate.swift b/Sources/JavaScriptKit/BasicObjects/JSDate.swift index 9157796bc..ba4f9b0a6 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSDate.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSDate.swift @@ -7,8 +7,8 @@ /// property if you need those. public final class JSDate: JSBridgedClass { /// The constructor function used to create new `Date` objects. - public static var constructor: JSFunction? { _constructor.wrappedValue } - private static let _constructor = LazyThreadLocal(initialize: { JSObject.global.Date.function }) + public static var constructor: JSObject? { _constructor.wrappedValue } + private static let _constructor = LazyThreadLocal(initialize: { JSObject.global.Date.object }) /// The underlying JavaScript `Date` object. public let jsObject: JSObject diff --git a/Sources/JavaScriptKit/BasicObjects/JSError.swift b/Sources/JavaScriptKit/BasicObjects/JSError.swift index 38accb97b..a2d385e99 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSError.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSError.swift @@ -3,8 +3,8 @@ /// exposes its properties in a type-safe way. public final class JSError: JSBridgedClass { /// The constructor function used to create new JavaScript `Error` objects. - public static var constructor: JSFunction? { _constructor.wrappedValue } - private static let _constructor = LazyThreadLocal(initialize: { JSObject.global.Error.function }) + public static var constructor: JSObject? { _constructor.wrappedValue } + private static let _constructor = LazyThreadLocal(initialize: { JSObject.global.Error.object }) /// The underlying JavaScript `Error` object. public let jsObject: JSObject diff --git a/Sources/JavaScriptKit/BasicObjects/JSPromise.swift b/Sources/JavaScriptKit/BasicObjects/JSPromise.swift index ec2a77248..c02ab44b0 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSPromise.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSPromise.swift @@ -1,3 +1,7 @@ +#if hasFeature(Embedded) && os(WASI) +import _Concurrency +#endif + /// A wrapper around [the JavaScript `Promise` class](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise) public final class JSPromise: JSBridgedClass { /// The underlying JavaScript `Promise` object. @@ -8,8 +12,8 @@ public final class JSPromise: JSBridgedClass { .object(jsObject) } - public static var constructor: JSFunction? { - JSObject.global.Promise.function! + public static var constructor: JSObject? { + JSObject.global.Promise.object! } /// This private initializer assumes that the passed object is a JavaScript `Promise` @@ -23,15 +27,11 @@ public final class JSPromise: JSBridgedClass { self.init(from: jsObject) } - @_spi(BridgeJS) public convenience init(takingThis: Int32) { - self.init(unsafelyWrapping: JSObject(id: UInt32(bitPattern: takingThis))) - } - /// Creates a new `JSPromise` instance from a given JavaScript `Promise` object. If `value` /// is not an object and is not an instance of JavaScript `Promise`, this function will /// return `nil`. 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) } @@ -54,8 +54,8 @@ public final class JSPromise: JSBridgedClass { let closure = JSOneshotClosure { arguments in // The arguments are always coming from the `Promise` constructor, so we should be // safe to assume their type here - let resolve = arguments[0].function! - let reject = arguments[1].function! + let resolve = arguments[0].object! + let reject = arguments[1].object! resolver { switch $0 { diff --git a/Sources/JavaScriptKit/BasicObjects/JSTimer.swift b/Sources/JavaScriptKit/BasicObjects/JSTimer.swift index 3655a185c..edfea163f 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSTimer.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSTimer.swift @@ -75,9 +75,9 @@ public final class JSTimer { } self.isRepeating = isRepeating if isRepeating { - value = global.setInterval.function!(arguments: [closure.jsValue, millisecondsDelay.jsValue]) + value = global.setInterval.object!(arguments: [closure.jsValue, millisecondsDelay.jsValue]) } else { - value = global.setTimeout.function!(arguments: [closure.jsValue, millisecondsDelay.jsValue]) + value = global.setTimeout.object!(arguments: [closure.jsValue, millisecondsDelay.jsValue]) } } @@ -87,9 +87,9 @@ public final class JSTimer { */ deinit { if isRepeating { - global.clearInterval.function!(value) + global.clearInterval.object!(value) } else { - global.clearTimeout.function!(value) + global.clearTimeout.object!(value) } closure.release() } diff --git a/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift b/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift index 47919b17d..dceecf5bf 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift @@ -7,7 +7,7 @@ import _CJavaScriptKit public protocol TypedArrayElement { associatedtype Element: ConvertibleToJSValue, ConstructibleFromJSValue = Self /// The constructor function for the TypedArray class for this particular kind of number - static var typedArrayClass: JSFunction { get } + static var typedArrayClass: JSObject { get } } /// A wrapper around all [JavaScript `TypedArray` @@ -15,7 +15,7 @@ public protocol TypedArrayElement { /// that exposes their properties in a type-safe way. public final class JSTypedArray: JSBridgedClass, ExpressibleByArrayLiteral where Traits: TypedArrayElement { public typealias Element = Traits.Element - public class var constructor: JSFunction? { Traits.typedArrayClass } + public class var constructor: JSObject? { Traits.typedArrayClass } public var jsObject: JSObject public subscript(_ index: Int) -> Element { @@ -141,11 +141,11 @@ public final class JSTypedArray: JSBridgedClass, ExpressibleByArrayLiter } extension Int: TypedArrayElement { - public static var typedArrayClass: JSFunction { + public static var typedArrayClass: JSObject { #if _pointerBitWidth(_32) - return JSObject.global.Int32Array.function! + return JSObject.global.Int32Array.object! #elseif _pointerBitWidth(_64) - return JSObject.global.Int64Array.function! + return JSObject.global.Int64Array.object! #else #error("Unsupported pointer width") #endif @@ -153,11 +153,11 @@ extension Int: TypedArrayElement { } extension UInt: TypedArrayElement { - public static var typedArrayClass: JSFunction { + public static var typedArrayClass: JSObject { #if _pointerBitWidth(_32) - return JSObject.global.Uint32Array.function! + return JSObject.global.Uint32Array.object! #elseif _pointerBitWidth(_64) - return JSObject.global.Uint64Array.function! + return JSObject.global.Uint64Array.object! #else #error("Unsupported pointer width") #endif @@ -165,40 +165,40 @@ extension UInt: TypedArrayElement { } extension Int8: TypedArrayElement { - public static var typedArrayClass: JSFunction { JSObject.global.Int8Array.function! } + public static var typedArrayClass: JSObject { JSObject.global.Int8Array.object! } } extension UInt8: TypedArrayElement { - public static var typedArrayClass: JSFunction { JSObject.global.Uint8Array.function! } + public static var typedArrayClass: JSObject { JSObject.global.Uint8Array.object! } } extension Int16: TypedArrayElement { - public static var typedArrayClass: JSFunction { JSObject.global.Int16Array.function! } + public static var typedArrayClass: JSObject { JSObject.global.Int16Array.object! } } extension UInt16: TypedArrayElement { - public static var typedArrayClass: JSFunction { JSObject.global.Uint16Array.function! } + public static var typedArrayClass: JSObject { JSObject.global.Uint16Array.object! } } extension Int32: TypedArrayElement { - public static var typedArrayClass: JSFunction { JSObject.global.Int32Array.function! } + public static var typedArrayClass: JSObject { JSObject.global.Int32Array.object! } } extension UInt32: TypedArrayElement { - public static var typedArrayClass: JSFunction { JSObject.global.Uint32Array.function! } + public static var typedArrayClass: JSObject { JSObject.global.Uint32Array.object! } } extension Float32: TypedArrayElement { - public static var typedArrayClass: JSFunction { JSObject.global.Float32Array.function! } + public static var typedArrayClass: JSObject { JSObject.global.Float32Array.object! } } extension Float64: TypedArrayElement { - public static var typedArrayClass: JSFunction { JSObject.global.Float64Array.function! } + public static var typedArrayClass: JSObject { JSObject.global.Float64Array.object! } } public enum JSUInt8Clamped: TypedArrayElement { public typealias Element = UInt8 - public static var typedArrayClass: JSFunction { JSObject.global.Uint8ClampedArray.function! } + public static var typedArrayClass: JSObject { JSObject.global.Uint8ClampedArray.object! } } public typealias JSUInt8ClampedArray = JSTypedArray diff --git a/Sources/JavaScriptKit/BridgeJSInstrincics.swift b/Sources/JavaScriptKit/BridgeJSInstrincics.swift deleted file mode 100644 index 1a8bad7f9..000000000 --- a/Sources/JavaScriptKit/BridgeJSInstrincics.swift +++ /dev/null @@ -1,74 +0,0 @@ -import _CJavaScriptKit - -#if !arch(wasm32) -@usableFromInline func _onlyAvailableOnWasm() -> Never { - fatalError("Only available on WebAssembly") -} -#endif - -#if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_return_string") -@_spi(BridgeJS) public func _swift_js_return_string(_ ptr: UnsafePointer?, _ len: Int32) -#else -@_spi(BridgeJS) public func _swift_js_return_string(_ ptr: UnsafePointer?, _ len: Int32) { - _onlyAvailableOnWasm() -} -#endif - -#if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_init_memory") -@_spi(BridgeJS) public func _swift_js_init_memory(_ sourceId: Int32, _ ptr: UnsafeMutablePointer?) -#else -@_spi(BridgeJS) public func _swift_js_init_memory(_ sourceId: Int32, _ ptr: UnsafeMutablePointer?) { - _onlyAvailableOnWasm() -} -#endif - -#if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_retain") -@_spi(BridgeJS) public func _swift_js_retain(_ ptr: Int32) -> Int32 -#else -@_spi(BridgeJS) public func _swift_js_retain(_ ptr: Int32) -> Int32 { - _onlyAvailableOnWasm() -} -#endif - -#if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_throw") -@_spi(BridgeJS) public func _swift_js_throw(_ id: Int32) -#else -@_spi(BridgeJS) public func _swift_js_throw(_ id: Int32) { - _onlyAvailableOnWasm() -} -#endif - -#if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_make_js_string") -@_spi(BridgeJS) public func _swift_js_make_js_string(_ ptr: UnsafePointer?, _ len: Int32) -> Int32 -#else -@_spi(BridgeJS) public func _swift_js_make_js_string(_ ptr: UnsafePointer?, _ len: Int32) -> Int32 { - _onlyAvailableOnWasm() -} -#endif - -#if arch(wasm32) -@_extern(wasm, module: "bjs", name: "swift_js_init_memory_with_result") -@_spi(BridgeJS) public func _swift_js_init_memory_with_result(_ ptr: UnsafePointer?, _ len: Int32) -#else -@_spi(BridgeJS) public func _swift_js_init_memory_with_result(_ ptr: UnsafePointer?, _ len: Int32) { - _onlyAvailableOnWasm() -} -#endif - -@_spi(BridgeJS) @_transparent public func _swift_js_take_exception() -> JSException? { - #if arch(wasm32) - let value = _swift_js_exception_get() - if _fastPath(value == 0) { - return nil - } - _swift_js_exception_set(0) - return JSException(JSObject(id: UInt32(bitPattern: value)).jsValue) - #else - _onlyAvailableOnWasm() - #endif -} diff --git a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift new file mode 100644 index 000000000..28bdaa6db --- /dev/null +++ b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift @@ -0,0 +1,2381 @@ +/// BridgeJS Intrinsics +/// +/// This file contains low-level intrinsic functions that are used by code generated +/// by the BridgeJS system. + +import _CJavaScriptKit + +#if !arch(wasm32) +@usableFromInline func _onlyAvailableOnWasm() -> Never { + fatalError("Only available on WebAssembly") +} +#endif + +// MARK: Exception Handling + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_throw") +private func _swift_js_throw_extern(_ id: Int32) +#else +private func _swift_js_throw_extern(_ id: Int32) { + _onlyAvailableOnWasm() +} +#endif + +/// Throws a JavaScript exception from Swift code. +/// +/// This function is called by the BridgeJS code generator when a Swift function throws +/// an error. The exception object is retained and stored for later retrieval by the +/// JavaScript-side runtime code. +/// +/// - Parameter id: The ID of the JavaScript exception object to throw +@_spi(BridgeJS) @inline(never) public func _swift_js_throw(_ id: Int32) { + _swift_js_throw_extern(id) +} + +/// Retrieves and clears any pending JavaScript exception. +/// +/// This function checks for any JavaScript exceptions that were thrown during +/// the execution of imported JavaScript functions. If an exception exists, it +/// is retrieved, cleared from the global storage, and returned as a `JSException`. +/// +/// - Returns: A `JSException` if an exception was pending, `nil` otherwise +@_spi(BridgeJS) @_transparent public func _swift_js_take_exception() -> JSException? { + #if arch(wasm32) + let value = _swift_js_exception_get() + if _fastPath(value == 0) { + return nil + } + _swift_js_exception_set(0) + return JSException(JSObject(id: UInt32(bitPattern: value)).jsValue) + #else + _onlyAvailableOnWasm() + #endif +} + +/// Releases a Swift closure from the FinalizationRegistry +/// +/// This function is called by the BridgeJS code generator when a Swift closure is released. +/// The closure is released from the FinalizationRegistry so it can be garbage collected to +/// balance the +/// +/// - Parameter pointer: The pointer to `_BridgeJSTypedClosureBox` instance +@_expose(wasm, "bjs_release_swift_closure") +public func _bjs_release_swift_closure(_ pointer: UnsafeMutableRawPointer) { + Unmanaged.fromOpaque(pointer).release() +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_closure_unregister") +internal func _swift_js_closure_unregister(_ id: Int32) +#else +/// Unregisters a Swift closure from the FinalizationRegistry +/// +/// - Parameter id: The JavaScriptObjectRef of the JS closure object created by +/// the BridgeJS's `make_swift_closure_{signature}` function. +/// +/// - Note: This is a best-effort operation. +/// According to the ECMAScript specification, calling +/// `FinalizationRegistry.prototype.unregister` does not guarantee that +/// a finalization callback will be suppressed if the target object has +/// already been garbage-collected and cleanup has been scheduled. +/// This means that the finalization callback should be tolerant of the +/// object being already collected. +/// See: https://tc39.es/ecma262/multipage/managing-memory.html#sec-finalization-registry.prototype.unregister +internal func _swift_js_closure_unregister(_ id: Int32) { + _onlyAvailableOnWasm() +} +#endif + +// MARK: Type lowering/lifting +// +// The following part defines the parameter and return value lowering/lifting +// for a given type. They follow the following pattern: +// +// ```swift +// extension <#TargetType#> { +// // MARK: ImportTS +// @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> <#WasmCoreType#> { +// } +// @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ ...) -> <#Self#> { +// } +// // MARK: ExportSwift +// @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ ...) -> <#Self#> { +// } +// @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> <#WasmCoreType#> { +// } +// // MARK: Stack ABI +// @_spi(BridgeJS) public static func bridgeJSStackPop() -> <#Self#> { +// } +// @_spi(BridgeJS) public consuming func bridgeJSStackPush() { +// } +// } +// ``` +// +// where: +// - <#TargetType#>: the higher-level type to be lowered/lifted +// - <#WasmCoreType#>: the corresponding WebAssembly core type or Void +// - `func bridgeJSLowerParameter()`: lower the given higher-level parameter to a WebAssembly core type +// - `func bridgeJSLiftReturn(_ ...) -> <#TargetType#>`: lift the given Wasm core type return value to a higher-level type +// - `func bridgeJSLiftParameter(_ ...) -> <#TargetType#>`: lift the given Wasm core type parameters to a higher-level type +// - `func bridgeJSLowerReturn() -> <#WasmCoreType#>`: lower the given higher-level return value to a Wasm core type +// - `func bridgeJSStackPop() -> <#TargetType#>`: no-arg overload that pops parameters from the param stack internally. +// Note: Pop order must match Swift's left-to-right argument evaluation order. +// - `func bridgeJSStackPush()`: push the value onto the return stack (used by _BridgedSwiftStackType for array elements) +// +// Optional types (ExportSwift only) additionally define: +// - `func bridgeJSLowerParameterWithRetain()`: lower optional heap object with ownership transfer for escaping closures +// - `func bridgeJSLiftReturnFromSideChannel()`: lift optional from side-channel storage for protocol property getters +// +// See JSGlueGen.swift in BridgeJSLink for JS-side lowering/lifting implementation. + +/// A protocol that Swift types that can appear as parameters or return values on +public protocol _BridgedSwiftTypeLoweredIntoSingleWasmCoreType { + associatedtype WasmCoreType + // MARK: ImportTS + consuming func bridgeJSLowerParameter() -> WasmCoreType + static func bridgeJSLiftReturn(_ value: WasmCoreType) -> Self + // MARK: ExportSwift + static func bridgeJSLiftParameter(_ value: WasmCoreType) -> Self + consuming func bridgeJSLowerReturn() -> WasmCoreType +} + +public protocol _BridgedSwiftStackType { + associatedtype StackLiftResult = Self + static func bridgeJSStackPop() -> StackLiftResult + consuming func bridgeJSStackPush() +} + +/// Types that bridge with the same (isSome, value) ABI as Optional. +/// Used by JSUndefinedOr so all bridge methods delegate to Optional. +public protocol _BridgedAsOptional { + associatedtype Wrapped + var asOptional: Wrapped? { get } + init(optional: Wrapped?) +} + +extension Bool: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType { + // MARK: ImportTS + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + self ? 1 : 0 + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Bool { + value == 1 + } + // MARK: ExportSwift + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Bool { + value == 1 + } + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Bool { + bridgeJSLiftParameter(_swift_js_pop_i32()) + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + self ? 1 : 0 + } + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_i32(self ? 1 : 0) + } +} + +extension Int: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType { + // MARK: ImportTS + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + Int32(self) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Int { + Int(value) + } + // MARK: ExportSwift + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Int { + Int(value) + } + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Int { + bridgeJSLiftParameter(_swift_js_pop_i32()) + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + Int32(self) + } + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_i32(Int32(self)) + } +} + +extension UInt: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType { + // 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) public static func bridgeJSStackPop() -> UInt { + bridgeJSLiftParameter(_swift_js_pop_i32()) + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + Int32(bitPattern: UInt32(self)) + } + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_i32(Int32(bitPattern: UInt32(self))) + } +} + +extension Int32: _BridgedSwiftStackType { + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Int32 { + _swift_js_pop_i32() + } + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_i32(self) + } +} + +extension Int64: _BridgedSwiftStackType { + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Int64 { + Int64(_swift_js_pop_i32()) + } + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_i32(Int32(self)) + } +} + +extension UInt32: _BridgedSwiftStackType { + @_spi(BridgeJS) public static func bridgeJSStackPop() -> UInt32 { + UInt32(bitPattern: _swift_js_pop_i32()) + } + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_i32(Int32(bitPattern: self)) + } +} + +extension UInt64: _BridgedSwiftStackType { + @_spi(BridgeJS) public static func bridgeJSStackPop() -> UInt64 { + UInt64(UInt32(bitPattern: _swift_js_pop_i32())) + } + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_i32(Int32(bitPattern: UInt32(self))) + } +} + +extension Float: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType { + // MARK: ImportTS + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Float32 { + Float32(self) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Float32) -> Float { + Float(value) + } + // MARK: ExportSwift + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Float32) -> Float { + Float(value) + } + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Float { + bridgeJSLiftParameter(_swift_js_pop_f32()) + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Float32 { + Float32(self) + } + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_f32(Float32(self)) + } +} + +extension Double: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType { + // MARK: ImportTS + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Float64 { + Float64(self) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Float64) -> Double { + Double(value) + } + // MARK: ExportSwift + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Float64) -> Double { + Double(value) + } + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Double { + bridgeJSLiftParameter(_swift_js_pop_f64()) + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Float64 { + Float64(self) + } + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_f64(Float64(self)) + } +} + +extension String: _BridgedSwiftStackType { + public typealias StackLiftResult = String + + // MARK: ImportTS + + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Int32 { + return self.withUTF8 { b in + _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) + } + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ bytesCount: Int32) -> String { + #if !arch(wasm32) + guard #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) else { _onlyAvailableOnWasm() } + #endif + return String(unsafeUninitializedCapacity: Int(bytesCount)) { b in + _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(bytesCount)) + return Int(bytesCount) + } + } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ bytes: Int32, _ count: Int32) -> String { + #if !arch(wasm32) + guard #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) else { _onlyAvailableOnWasm() } + #endif + return String(unsafeUninitializedCapacity: Int(count)) { b in + _swift_js_init_memory(bytes, b.baseAddress.unsafelyUnwrapped) + return Int(count) + } + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> String { + let bytes = _swift_js_pop_i32() + let count = _swift_js_pop_i32() + return bridgeJSLiftParameter(bytes, count) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + return self.withUTF8 { ptr in + _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) + } + } + + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + self.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + } +} + +extension JSObject: _BridgedSwiftStackType { + // JSObject is a non-final class, so we must explicitly specify the associated type + // rather than relying on the default `Self` (which Swift requires for covariant returns). + public typealias StackLiftResult = JSObject + + // MARK: ImportTS + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + Int32(bitPattern: self.id) + } + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ id: Int32) -> JSObject { + JSObject(id: JavaScriptObjectRef(bitPattern: id)) + } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ id: Int32) -> JSObject { + JSObject(id: JavaScriptObjectRef(bitPattern: id)) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> JSObject { + bridgeJSLiftParameter(_swift_js_pop_i32()) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Int32 { + return _swift_js_retain(Int32(bitPattern: self.id)) + } + + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_i32(bridgeJSLowerReturn()) + } +} + +extension JSValue: _BridgedSwiftStackType { + public typealias StackLiftResult = JSValue + + @_transparent + private static func bridgeJSRetainPayloadIfNeeded(kind: Int32, payload1: Int32) -> Int32 { + guard let kindEnum = JavaScriptValueKind(rawValue: UInt32(kind)) else { + return payload1 + } + switch kindEnum { + case .string, .object, .symbol, .bigInt: + return _swift_js_retain(payload1) + default: + return payload1 + } + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> JSValue { + let payload2 = _swift_js_pop_f64() + let payload1 = _swift_js_pop_i32() + let kind = _swift_js_pop_i32() + return bridgeJSLiftParameter(kind, payload1, payload2) + } + + @_spi(BridgeJS) public consuming func bridgeJSStackPush() -> Void { + let lowered = bridgeJSLowerParameter() + let retainedPayload1 = Self.bridgeJSRetainPayloadIfNeeded(kind: lowered.kind, payload1: lowered.payload1) + _swift_js_push_i32(lowered.kind) + _swift_js_push_i32(retainedPayload1) + _swift_js_push_f64(lowered.payload2) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (kind: Int32, payload1: Int32, payload2: Double) { + return withRawJSValue { raw in + ( + kind: Int32(raw.kind.rawValue), + payload1: Int32(bitPattern: raw.payload1), + payload2: raw.payload2 + ) + } + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter( + _ kind: Int32, + _ payload1: Int32, + _ payload2: Double + ) -> JSValue { + let retainedPayload1 = bridgeJSRetainPayloadIfNeeded(kind: kind, payload1: payload1) + + guard let kindEnum = JavaScriptValueKind(rawValue: UInt32(kind)) else { + fatalError("Invalid JSValue kind: \(kind)") + } + let rawValue = RawJSValue( + kind: kindEnum, + payload1: JavaScriptPayload1(UInt32(bitPattern: retainedPayload1)), + payload2: payload2 + ) + return rawValue.jsValue + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturn() -> JSValue { + bridgeJSStackPop() + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() { + bridgeJSStackPush() + } +} + +/// A protocol that Swift heap objects exposed to JavaScript via `@JS class` must conform to. +/// +/// The conformance is automatically synthesized by the BridgeJS code generator. +public protocol _BridgedSwiftHeapObject: AnyObject, _BridgedSwiftStackType {} + +/// Define the lowering/lifting for `_BridgedSwiftHeapObject` +extension _BridgedSwiftHeapObject { + + // MARK: ImportTS + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> UnsafeMutableRawPointer { + // For protocol parameters, we pass the unretained pointer since JS already has a reference + return Unmanaged.passUnretained(self).toOpaque() + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ pointer: UnsafeMutableRawPointer) -> Self { + // For protocol returns, take an unretained value since JS manages the lifetime + return Unmanaged.fromOpaque(pointer).takeUnretainedValue() + } + + // MARK: ExportSwift + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ pointer: UnsafeMutableRawPointer) -> Self { + Unmanaged.fromOpaque(pointer).takeUnretainedValue() + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> UnsafeMutableRawPointer { + // Perform a manual retain on the object, which will be balanced by a release called via FinalizationRegistry + return Unmanaged.passRetained(self).toOpaque() + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + bridgeJSLiftParameter(_swift_js_pop_pointer()) + } + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_pointer(Unmanaged.passRetained(self).toOpaque()) + } +} +// MARK: Closure Box Protocol + +/// A protocol that Swift closure box types must conform to. +/// +/// The conformance is automatically synthesized by the BridgeJS code generator. +@_spi(BridgeJS) public protocol _BridgedSwiftClosureBox: AnyObject {} + +extension _JSBridgedClass { + // MARK: ImportTS + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Int32 { jsObject.bridgeJSLowerParameter() } + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ id: Int32) -> Self { + Self(unsafelyWrapping: JSObject.bridgeJSLiftReturn(id)) + } + + // MARK: ExportSwift + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ id: Int32) -> Self { + Self(unsafelyWrapping: JSObject.bridgeJSLiftParameter(id)) + } + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + bridgeJSLiftParameter(_swift_js_pop_i32()) + } + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Int32 { jsObject.bridgeJSLowerReturn() } + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_i32(bridgeJSLowerReturn()) + } +} + +/// A protocol that Swift protocol wrappers exposed from JavaScript must conform to. +/// +/// The conformance is automatically synthesized by the BridgeJS code generator. +public protocol _BridgedSwiftProtocolWrapper: _BridgedSwiftStackType { + var jsObject: JSObject { get } + static func bridgeJSLiftParameter(_ value: Int32) -> Self +} + +extension _BridgedSwiftProtocolWrapper { + // MARK: ExportSwift + @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Self { + bridgeJSStackPop() + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Int32 { + jsObject.bridgeJSLowerReturn() + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Int32 { + jsObject.bridgeJSLowerParameter() + } + + // MARK: Stack ABI + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + bridgeJSLiftParameter(_swift_js_pop_i32()) + } + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_i32(jsObject.bridgeJSLowerReturn()) + } +} + +/// A protocol that Swift enum types that do not have a payload can conform to. +/// +/// The conformance is automatically synthesized by the BridgeJS code generator. +public protocol _BridgedSwiftEnumNoPayload {} + +/// A protocol for raw value enums that enables automatic stack operations. +/// +/// Conforming to this protocol provides default implementations of `_BridgedSwiftStackType` +/// methods by delegating to the raw value's stack operations. The raw value type must itself +/// conform to `_BridgedSwiftStackType`. +/// +/// The conformance is automatically synthesized by the BridgeJS code generator. +public protocol _BridgedSwiftRawValueEnum: _BridgedSwiftStackType, RawRepresentable +where RawValue: _BridgedSwiftStackType, RawValue.StackLiftResult == RawValue {} + +extension _BridgedSwiftRawValueEnum { + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + Self(rawValue: RawValue.bridgeJSStackPop())! + } + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + rawValue.bridgeJSStackPush() + } +} + +/// A protocol that Swift case enum types (enums without raw values or associated values) conform to. +/// +/// The conformance is automatically synthesized by the BridgeJS code generator. +public protocol _BridgedSwiftCaseEnum: _BridgedSwiftStackType { + // MARK: ImportTS + @_spi(BridgeJS) consuming func bridgeJSLowerParameter() -> Int32 + @_spi(BridgeJS) static func bridgeJSLiftReturn(_ value: Int32) -> Self + + // MARK: ExportSwift + @_spi(BridgeJS) static func bridgeJSLiftParameter(_ value: Int32) -> Self + @_spi(BridgeJS) consuming func bridgeJSLowerReturn() -> Int32 +} + +extension _BridgedSwiftCaseEnum { + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + bridgeJSLiftParameter(_swift_js_pop_i32()) + } + + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_i32(bridgeJSLowerReturn()) + } +} + +/// A protocol that Swift associated value enum types conform to. +/// +/// The conformance is automatically synthesized by the BridgeJS code generator. +public protocol _BridgedSwiftAssociatedValueEnum: _BridgedSwiftTypeLoweredIntoVoidType, _BridgedSwiftStackType { + /// Pops the payload of the associated value enum from the stack. + /// + /// - Parameter caseId: The enum case ID. + /// - Returns: The associated value enum with its payload popped from the stack. + @_spi(BridgeJS) static func bridgeJSStackPopPayload(_ caseId: Int32) -> Self + + /// Pushes the payload of the associated value enum onto the stack. + /// + /// - Returns: The enum case ID. + @_spi(BridgeJS) consuming func bridgeJSStackPushPayload() -> Int32 +} + +extension _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + bridgeJSStackPopPayload(_swift_js_pop_i32()) + } + + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_i32(bridgeJSStackPushPayload()) + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ caseId: Int32) -> Self { + return bridgeJSStackPopPayload(caseId) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() { + bridgeJSStackPush() + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSStackPushPayload() + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ caseId: Int32) -> Self { + return bridgeJSStackPopPayload(caseId) + } +} + +/// A protocol that Swift struct types conform to. +/// +/// The conformance is automatically synthesized by the BridgeJS code generator. +public protocol _BridgedSwiftStruct: _BridgedSwiftTypeLoweredIntoVoidType, _BridgedSwiftGenericOptionalStackType { + // MARK: ExportSwift + @_spi(BridgeJS) static func bridgeJSStackPop() -> Self + @_spi(BridgeJS) consuming func bridgeJSStackPush() -> 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) + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Self { + bridgeJSStackPop() + } + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() { + bridgeJSStackPush() + } +} + +extension _BridgedSwiftEnumNoPayload where Self: RawRepresentable, RawValue == String { + // MARK: ImportTS + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Int32 { rawValue.bridgeJSLowerParameter() } + + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ id: Int32) -> Self { + Self(rawValue: .bridgeJSLiftReturn(id))! + } + + // MARK: ExportSwift + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ bytes: Int32, _ count: Int32) -> Self { + Self(rawValue: .bridgeJSLiftParameter(bytes, count))! + } + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { rawValue.bridgeJSLowerReturn() } +} + +extension _BridgedSwiftEnumNoPayload +where Self: RawRepresentable, RawValue: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType { + // MARK: ImportTS + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> RawValue.WasmCoreType { + rawValue.bridgeJSLowerParameter() + } + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ value: RawValue.WasmCoreType) -> Self { + Self(rawValue: .bridgeJSLiftReturn(value))! + } + + // MARK: ExportSwift + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ value: RawValue.WasmCoreType) -> Self { + Self(rawValue: .bridgeJSLiftParameter(value))! + } + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> RawValue.WasmCoreType { + rawValue.bridgeJSLowerReturn() + } +} + +// MARK: Wasm externs used by generated enum glue + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_init_memory") +private func _swift_js_init_memory_extern(_ sourceId: Int32, _ ptr: UnsafeMutablePointer) +#else +private func _swift_js_init_memory_extern(_ sourceId: Int32, _ ptr: UnsafeMutablePointer) { + _onlyAvailableOnWasm() +} +#endif + +/// Initializes WebAssembly memory with a Uint8Array referenced by `sourceId` at `ptr`. +/// Note that the ownership of the source Uint8Array id is taken by the callee, so callers +/// must not release the source Uint8Array id by themselves. +/// +/// - Parameter sourceId: The object ID of the source Uint8Array. +/// - Parameter ptr: The pointer to the WebAssembly memory to initialize. +@_spi(BridgeJS) @inline(never) public func _swift_js_init_memory(_ sourceId: Int32, _ ptr: UnsafeMutablePointer) +{ + _swift_js_init_memory_extern(sourceId, ptr) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_push_string") +private func _swift_js_push_string_extern(_ ptr: UnsafePointer?, _ len: Int32) +#else +private func _swift_js_push_string_extern(_ ptr: UnsafePointer?, _ len: Int32) { + _onlyAvailableOnWasm() +} +#endif + +@_spi(BridgeJS) @inline(never) public func _swift_js_push_string(_ ptr: UnsafePointer?, _ len: Int32) { + _swift_js_push_string_extern(ptr, len) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_push_i32") +private func _swift_js_push_i32_extern(_ value: Int32) +#else +private func _swift_js_push_i32_extern(_ value: Int32) { + _onlyAvailableOnWasm() +} +#endif + +@_spi(BridgeJS) @inline(never) public func _swift_js_push_i32(_ value: Int32) { + _swift_js_push_i32_extern(value) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_push_f32") +private func _swift_js_push_f32_extern(_ value: Float32) +#else +private func _swift_js_push_f32_extern(_ value: Float32) { + _onlyAvailableOnWasm() +} +#endif + +@_spi(BridgeJS) @inline(never) public func _swift_js_push_f32(_ value: Float32) { + _swift_js_push_f32_extern(value) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_push_f64") +private func _swift_js_push_f64_extern(_ value: Float64) +#else +private func _swift_js_push_f64_extern(_ value: Float64) { + _onlyAvailableOnWasm() +} +#endif + +@_spi(BridgeJS) @inline(never) public func _swift_js_push_f64(_ value: Float64) { + _swift_js_push_f64_extern(value) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_pop_i32") +private func _swift_js_pop_i32_extern() -> Int32 +#else +private func _swift_js_pop_i32_extern() -> Int32 { + _onlyAvailableOnWasm() +} +#endif + +@_spi(BridgeJS) @inline(never) public func _swift_js_pop_i32() -> Int32 { + _swift_js_pop_i32_extern() +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_pop_f32") +private func _swift_js_pop_f32_extern() -> Float32 +#else +private func _swift_js_pop_f32_extern() -> Float32 { + _onlyAvailableOnWasm() +} +#endif + +@_spi(BridgeJS) @inline(never) public func _swift_js_pop_f32() -> Float32 { + _swift_js_pop_f32_extern() +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_pop_f64") +private func _swift_js_pop_f64_extern() -> Float64 +#else +private func _swift_js_pop_f64_extern() -> Float64 { + _onlyAvailableOnWasm() +} +#endif + +@_spi(BridgeJS) @inline(never) public func _swift_js_pop_f64() -> Float64 { + _swift_js_pop_f64_extern() +} + +// MARK: Struct bridging helpers (JS-side lowering/raising) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_cleanup") +private func _swift_js_struct_cleanup_extern(_ cleanupId: Int32) +#else +private func _swift_js_struct_cleanup_extern(_ cleanupId: Int32) { + _onlyAvailableOnWasm() +} +#endif + +@_spi(BridgeJS) @inline(never) public func _swift_js_struct_cleanup(_ cleanupId: Int32) { + _swift_js_struct_cleanup_extern(cleanupId) +} + +// MARK: Wasm externs used by type lowering/lifting + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_make_js_string") +func _swift_js_make_js_string(_ ptr: UnsafePointer?, _ len: Int32) -> Int32 +#else +/// Creates a JavaScript string from UTF-8 data in WebAssembly memory +func _swift_js_make_js_string(_ ptr: UnsafePointer?, _ len: Int32) -> Int32 { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_init_memory_with_result") +func _swift_js_init_memory_with_result(_ ptr: UnsafePointer?, _ len: Int32) +#else +/// Initializes WebAssembly memory with result data of JavaScript function call +func _swift_js_init_memory_with_result(_ ptr: UnsafePointer?, _ len: Int32) { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_return_string") +func _swift_js_return_string(_ ptr: UnsafePointer?, _ len: Int32) +#else +/// Write a string to reserved string storage to be returned to JavaScript +func _swift_js_return_string(_ ptr: UnsafePointer?, _ len: Int32) { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_retain") +func _swift_js_retain(_ id: Int32) -> Int32 +#else +/// Retains a JavaScript object reference to ensure the object id +/// remains valid after the function returns +func _swift_js_retain(_ id: Int32) -> Int32 { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_return_optional_bool") +func _swift_js_return_optional_bool(_ isSome: Int32, _ value: Int32) +#else +/// Sets the optional bool for return value storage +func _swift_js_return_optional_bool(_ isSome: Int32, _ value: Int32) { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_get_optional_int_presence") +func _swift_js_get_optional_int_presence() -> Int32 +#else +func _swift_js_get_optional_int_presence() -> Int32 { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_get_optional_int_value") +func _swift_js_get_optional_int_value() -> Int32 +#else +func _swift_js_get_optional_int_value() -> Int32 { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_return_optional_int") +func _swift_js_return_optional_int(_ isSome: Int32, _ value: Int32) +#else +/// Sets the optional int for return value storage +func _swift_js_return_optional_int(_ isSome: Int32, _ value: Int32) { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_get_optional_string") +func _swift_js_get_optional_string() -> Int32 +#else +func _swift_js_get_optional_string() -> Int32 { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_return_optional_string") +func _swift_js_return_optional_string(_ isSome: Int32, _ ptr: UnsafePointer?, _ len: Int32) +#else +/// Write an optional string to reserved string storage to be returned to JavaScript +func _swift_js_return_optional_string(_ isSome: Int32, _ ptr: UnsafePointer?, _ len: Int32) { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_return_optional_object") +func _swift_js_return_optional_object(_ isSome: Int32, _ objectId: Int32) +#else +/// Write an optional JSObject to reserved storage to be returned to JavaScript +func _swift_js_return_optional_object(_ isSome: Int32, _ objectId: Int32) { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_get_optional_heap_object_pointer") +func _swift_js_get_optional_heap_object_pointer() -> UnsafeMutableRawPointer +#else +func _swift_js_get_optional_heap_object_pointer() -> UnsafeMutableRawPointer { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_return_optional_heap_object") +func _swift_js_return_optional_heap_object(_ isSome: Int32, _ pointer: UnsafeMutableRawPointer?) +#else +/// Write an optional Swift heap object to reserved storage to be returned to JavaScript +func _swift_js_return_optional_heap_object(_ isSome: Int32, _ pointer: UnsafeMutableRawPointer?) { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_get_optional_float_presence") +func _swift_js_get_optional_float_presence() -> Int32 +#else +func _swift_js_get_optional_float_presence() -> Int32 { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_get_optional_float_value") +func _swift_js_get_optional_float_value() -> Float32 +#else +func _swift_js_get_optional_float_value() -> Float32 { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_return_optional_float") +func _swift_js_return_optional_float(_ isSome: Int32, _ value: Float32) +#else +/// Sets the optional float for return value storage +func _swift_js_return_optional_float(_ isSome: Int32, _ value: Float32) { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_get_optional_double_presence") +func _swift_js_get_optional_double_presence() -> Int32 +#else +func _swift_js_get_optional_double_presence() -> Int32 { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_get_optional_double_value") +func _swift_js_get_optional_double_value() -> Float64 +#else +func _swift_js_get_optional_double_value() -> Float64 { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_return_optional_double") +func _swift_js_return_optional_double(_ isSome: Int32, _ value: Float64) +#else +/// Sets the optional double for return value storage +func _swift_js_return_optional_double(_ isSome: Int32, _ value: Float64) { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_push_pointer") +private func _swift_js_push_pointer_extern(_ pointer: UnsafeMutableRawPointer) +#else +private func _swift_js_push_pointer_extern(_ pointer: UnsafeMutableRawPointer) { + _onlyAvailableOnWasm() +} +#endif + +@_spi(BridgeJS) @inline(never) public func _swift_js_push_pointer(_ pointer: UnsafeMutableRawPointer) { + _swift_js_push_pointer_extern(pointer) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_pop_pointer") +private func _swift_js_pop_pointer_extern() -> UnsafeMutableRawPointer +#else +private func _swift_js_pop_pointer_extern() -> UnsafeMutableRawPointer { + _onlyAvailableOnWasm() +} +#endif + +@_spi(BridgeJS) @inline(never) public func _swift_js_pop_pointer() -> UnsafeMutableRawPointer { + _swift_js_pop_pointer_extern() +} + +// MARK: - UnsafePointer family + +public protocol _BridgedSwiftUnsafePointerLike: _BridgedSwiftStackType { + @_spi(BridgeJS) func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer + @_spi(BridgeJS) static func bridgeJSFromUnsafeMutableRawPointer(_ pointer: UnsafeMutableRawPointer) -> Self +} + +extension _BridgedSwiftUnsafePointerLike { + // MARK: ImportTS + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> UnsafeMutableRawPointer { + bridgeJSToUnsafeMutableRawPointer() + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ pointer: UnsafeMutableRawPointer) -> Self { + bridgeJSFromUnsafeMutableRawPointer(pointer) + } + + // MARK: ExportSwift + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ pointer: UnsafeMutableRawPointer) -> Self { + bridgeJSFromUnsafeMutableRawPointer(pointer) + } + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + bridgeJSLiftParameter(_swift_js_pop_pointer()) + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> UnsafeMutableRawPointer { + bridgeJSToUnsafeMutableRawPointer() + } + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_pointer(bridgeJSToUnsafeMutableRawPointer()) + } +} + +extension UnsafeMutableRawPointer: _BridgedSwiftUnsafePointerLike { + @_spi(BridgeJS) @_transparent public func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer { self } + @_spi(BridgeJS) @_transparent public static func bridgeJSFromUnsafeMutableRawPointer( + _ pointer: UnsafeMutableRawPointer + ) -> UnsafeMutableRawPointer { + pointer + } +} + +extension UnsafeRawPointer: _BridgedSwiftUnsafePointerLike { + @_spi(BridgeJS) @_transparent public func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer { + UnsafeMutableRawPointer(mutating: self) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSFromUnsafeMutableRawPointer( + _ pointer: UnsafeMutableRawPointer + ) -> UnsafeRawPointer { + UnsafeRawPointer(pointer) + } +} + +extension OpaquePointer: _BridgedSwiftUnsafePointerLike { + @_spi(BridgeJS) @_transparent public func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer { + UnsafeMutableRawPointer(mutating: UnsafeRawPointer(self)) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSFromUnsafeMutableRawPointer( + _ pointer: UnsafeMutableRawPointer + ) -> OpaquePointer { + OpaquePointer(UnsafeRawPointer(pointer)) + } +} + +extension UnsafePointer: _BridgedSwiftUnsafePointerLike { + @_spi(BridgeJS) @_transparent public func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer { + UnsafeMutableRawPointer(mutating: UnsafeRawPointer(self)) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSFromUnsafeMutableRawPointer( + _ pointer: UnsafeMutableRawPointer + ) -> UnsafePointer { + UnsafeRawPointer(pointer).assumingMemoryBound(to: Pointee.self) + } +} + +extension UnsafeMutablePointer: _BridgedSwiftUnsafePointerLike { + @_spi(BridgeJS) @_transparent public func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer { + UnsafeMutableRawPointer(self) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSFromUnsafeMutableRawPointer( + _ pointer: UnsafeMutableRawPointer + ) -> UnsafeMutablePointer { + pointer.assumingMemoryBound(to: Pointee.self) + } +} + +// Optional support for JSTypedClosure +extension Optional { + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> ( + isSome: Int32, value: Int32 + ) where Wrapped == JSTypedClosure { + switch consume self { + case .none: + return (isSome: 0, value: 0) + case .some(let wrapped): + // Use return lowering to retain the JS function so JS lifting can fetch it from the heap. + return (isSome: 1, value: wrapped.bridgeJSLowerParameter()) + } + } +} + +extension Optional { + @usableFromInline @_transparent func _bridgeJSLowerParameter( + noneValue: Payload, + lowerWrapped: (Wrapped) -> Payload + ) -> (isSome: Int32, value: Payload) { + switch self { + case .none: + return (isSome: 0, value: noneValue) + case .some(let wrapped): + return (isSome: 1, value: lowerWrapped(wrapped)) + } + } + + @usableFromInline @_transparent static func _bridgeJSLiftParameter( + _ isSome: Int32, + _ payload: Payload, + liftWrapped: (Payload) -> Wrapped + ) -> Wrapped? { + if isSome == 0 { + return nil + } + return liftWrapped(payload) + } + + @usableFromInline @_transparent func _bridgeJSLowerReturn( + noneValue: Payload, + lowerWrapped: (Wrapped) -> Payload, + write: (Int32, Payload) -> Void + ) { + switch self { + case .none: + write(0, noneValue) + case .some(let wrapped): + write(1, lowerWrapped(wrapped)) + } + } +} + +public protocol _BridgedSwiftOptionalScalarBridge: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType { + @_spi(BridgeJS) static func bridgeJSPopOptionalScalarPayload() -> WasmCoreType + @_spi(BridgeJS) static var bridgeJSOptionalScalarNonePayload: WasmCoreType { get } + @_spi(BridgeJS) static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: WasmCoreType) +} + +public protocol _BridgedSwiftOptionalScalarSideChannelBridge: _BridgedSwiftOptionalScalarBridge { + @_spi(BridgeJS) static func bridgeJSReadOptionalSideChannelPresence() -> Int32 + @_spi(BridgeJS) static func bridgeJSReadOptionalSideChannelPayload() -> WasmCoreType +} + +extension Bool: _BridgedSwiftOptionalScalarBridge { + @_spi(BridgeJS) public static func bridgeJSPopOptionalScalarPayload() -> Int32 { _swift_js_pop_i32() } + @_spi(BridgeJS) public static var bridgeJSOptionalScalarNonePayload: Int32 { 0 } + @_spi(BridgeJS) public static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: Int32) { + _swift_js_return_optional_bool(isSome, value) + } +} + +extension Int: _BridgedSwiftOptionalScalarSideChannelBridge { + @_spi(BridgeJS) public static func bridgeJSPopOptionalScalarPayload() -> Int32 { _swift_js_pop_i32() } + @_spi(BridgeJS) public static var bridgeJSOptionalScalarNonePayload: Int32 { 0 } + @_spi(BridgeJS) public static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: Int32) { + _swift_js_return_optional_int(isSome, value) + } + @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPresence() -> Int32 { + _swift_js_get_optional_int_presence() + } + @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPayload() -> Int32 { + _swift_js_get_optional_int_value() + } +} + +extension UInt: _BridgedSwiftOptionalScalarSideChannelBridge { + @_spi(BridgeJS) public static func bridgeJSPopOptionalScalarPayload() -> Int32 { _swift_js_pop_i32() } + @_spi(BridgeJS) public static var bridgeJSOptionalScalarNonePayload: Int32 { 0 } + @_spi(BridgeJS) public static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: Int32) { + _swift_js_return_optional_int(isSome, value) + } + @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPresence() -> Int32 { + _swift_js_get_optional_int_presence() + } + @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPayload() -> Int32 { + _swift_js_get_optional_int_value() + } +} + +extension Float: _BridgedSwiftOptionalScalarSideChannelBridge { + @_spi(BridgeJS) public static func bridgeJSPopOptionalScalarPayload() -> Float32 { _swift_js_pop_f32() } + @_spi(BridgeJS) public static var bridgeJSOptionalScalarNonePayload: Float32 { 0.0 } + @_spi(BridgeJS) public static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: Float32) { + _swift_js_return_optional_float(isSome, value) + } + @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPresence() -> Int32 { + _swift_js_get_optional_float_presence() + } + @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPayload() -> Float32 { + _swift_js_get_optional_float_value() + } +} + +extension Double: _BridgedSwiftOptionalScalarSideChannelBridge { + @_spi(BridgeJS) public static func bridgeJSPopOptionalScalarPayload() -> Float64 { _swift_js_pop_f64() } + @_spi(BridgeJS) public static var bridgeJSOptionalScalarNonePayload: Float64 { 0.0 } + @_spi(BridgeJS) public static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: Float64) { + _swift_js_return_optional_double(isSome, value) + } + @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPresence() -> Int32 { + _swift_js_get_optional_double_presence() + } + @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPayload() -> Float64 { + _swift_js_get_optional_double_value() + } +} + +extension Optional where Wrapped: _BridgedSwiftOptionalScalarBridge { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> ( + isSome: Int32, value: Wrapped.WasmCoreType + ) { + switch consume self { + case .none: + return (isSome: 0, value: Wrapped.bridgeJSOptionalScalarNonePayload) + case .some(let wrapped): + return (isSome: 1, value: wrapped.bridgeJSLowerParameter()) + } + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter( + _ isSome: Int32, + _ wrappedValue: Wrapped.WasmCoreType + ) -> Wrapped? { + if isSome == 0 { + return nil + } + return Wrapped.bridgeJSLiftParameter(wrappedValue) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Wrapped? { + let isSome = _swift_js_pop_i32() + let wrappedValue = Wrapped.bridgeJSPopOptionalScalarPayload() + return bridgeJSLiftParameter(isSome, wrappedValue) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + switch consume self { + case .none: + Wrapped.bridgeJSWriteOptionalReturn(0, Wrapped.bridgeJSOptionalScalarNonePayload) + case .some(let value): + Wrapped.bridgeJSWriteOptionalReturn(1, value.bridgeJSLowerReturn()) + } + } +} + +extension Optional where Wrapped: _BridgedSwiftOptionalScalarSideChannelBridge { + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Wrapped? { + let isSome = Wrapped.bridgeJSReadOptionalSideChannelPresence() + if isSome == 0 { + return nil + } + return Wrapped.bridgeJSLiftReturn(Wrapped.bridgeJSReadOptionalSideChannelPayload()) + } +} + +extension Optional where Wrapped == Bool { + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ value: Int32) -> Bool? { + switch value { + case -1: + return nil + case 0: + return false + case 1: + return true + default: + return nil // Treat invalid values as null + } + } +} +extension Optional where Wrapped == String { + // MARK: ExportSwift + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> ( + isSome: Int32, value: Int32 + ) { + _bridgeJSLowerParameter(noneValue: 0, lowerWrapped: { $0.bridgeJSLowerParameter() }) + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ bytes: Int32, _ count: Int32) -> String? + { + _bridgeJSLiftParameter(isSome, (bytes, count), liftWrapped: { String.bridgeJSLiftParameter($0.0, $0.1) }) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> String? { + let isSome = _swift_js_pop_i32() + let bytes = _swift_js_pop_i32() + let count = _swift_js_pop_i32() + return bridgeJSLiftParameter(isSome, bytes, count) + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> String? { + let length = _swift_js_get_optional_string() + if length < 0 { + return nil + } else { + return String.bridgeJSLiftReturn(length) + } + } + + @_spi(BridgeJS) public func bridgeJSLowerReturn() -> Void { + switch self { + case .none: + _swift_js_return_optional_string(0, nil, 0) + case .some(var value): + return value.withUTF8 { ptr in + _swift_js_return_optional_string(1, ptr.baseAddress, Int32(ptr.count)) + } + } + } +} +extension Optional where Wrapped == JSObject { + // MARK: ExportSwift + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> ( + isSome: Int32, value: Int32 + ) { + _bridgeJSLowerParameter(noneValue: 0, lowerWrapped: { $0.bridgeJSLowerParameter() }) + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ objectId: Int32) -> JSObject? { + _bridgeJSLiftParameter(isSome, objectId, liftWrapped: JSObject.bridgeJSLiftParameter) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> JSObject? { + let isSome = _swift_js_pop_i32() + let objectId = _swift_js_pop_i32() + return bridgeJSLiftParameter(isSome, objectId) + } + + @_spi(BridgeJS) public func bridgeJSLowerReturn() -> Void { + _bridgeJSLowerReturn( + noneValue: 0, + lowerWrapped: { $0.bridgeJSLowerReturn() }, + write: _swift_js_return_optional_object + ) + } +} + +extension Optional where Wrapped == JSValue { + // MARK: ExportSwift + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> ( + isSome: Int32, kind: Int32, payload1: Int32, payload2: Double + ) { + switch consume self { + case .none: + return (isSome: 0, kind: 0, payload1: 0, payload2: 0) + case .some(let wrapped): + let lowered = wrapped.bridgeJSLowerParameter() + return ( + isSome: 1, + kind: lowered.kind, + payload1: lowered.payload1, + payload2: lowered.payload2 + ) + } + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter( + _ isSome: Int32, + _ kind: Int32, + _ payload1: Int32, + _ payload2: Double + ) -> JSValue? { + if isSome == 0 { + return nil + } else { + return JSValue.bridgeJSLiftParameter(kind, payload1, payload2) + } + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> JSValue? { + let isSome = _swift_js_pop_i32() + if isSome == 0 { + return nil + } + let payload2 = _swift_js_pop_f64() + let payload1 = _swift_js_pop_i32() + let kind = _swift_js_pop_i32() + return JSValue.bridgeJSLiftParameter(kind, payload1, payload2) + } + + @_spi(BridgeJS) public func bridgeJSLowerReturn() -> Void { + switch self { + case .none: + _swift_js_push_i32(0) + case .some(let value): + value.bridgeJSLowerReturn() + _swift_js_push_i32(1) + } + } +} + +extension Optional where Wrapped == [JSValue] { + // MARK: ExportSwift + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + switch consume self { + case .none: + return 0 + case .some(let array): + array.bridgeJSLowerReturn() + return 1 + } + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32) -> [JSValue]? { + if isSome == 0 { + return nil + } + return [JSValue].bridgeJSLiftParameter() + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturn() -> [JSValue]? { + let isSome = _swift_js_pop_i32() + if isSome == 0 { + return nil + } + return [JSValue].bridgeJSLiftReturn() + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + switch consume self { + case .none: + _swift_js_push_i32(0) + case .some(let array): + array.bridgeJSLowerReturn() + _swift_js_push_i32(1) + } + } +} + +extension Optional where Wrapped: _BridgedSwiftProtocolWrapper { + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ objectId: Int32) -> Wrapped? { + _bridgeJSLiftParameter(isSome, objectId, liftWrapped: Wrapped.bridgeJSLiftParameter) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + switch consume self { + case .none: + _swift_js_return_optional_object(0, 0) + case .some(let wrapper): + let retainedId: Int32 = wrapper.bridgeJSLowerReturn() + _swift_js_return_optional_object(1, retainedId) + } + } +} + +/// Optional support for Swift heap objects +extension Optional where Wrapped: _BridgedSwiftHeapObject { + // MARK: ExportSwift + /// Lowers optional Swift heap object as (isSome, pointer) tuple for protocol parameters. + /// + /// This method uses `passUnretained()` because the caller (JavaScript protocol implementation) + /// already owns the object and will not retain it. The pointer is only valid for the + /// duration of the call. + /// + /// - Returns: A tuple containing presence flag (0 for nil, 1 for some) and unretained pointer + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> ( + isSome: Int32, pointer: UnsafeMutableRawPointer + ) { + switch consume self { + case .none: + return (isSome: 0, pointer: UnsafeMutableRawPointer(bitPattern: 1)!) + case .some(let value): + return (isSome: 1, pointer: value.bridgeJSLowerParameter()) + } + } + + /// Lowers optional Swift heap object with ownership transfer for escaping closures. + /// + /// This method uses `passRetained()` to transfer ownership to JavaScript, ensuring the + /// object remains valid even if the JavaScript closure escapes and stores the parameter. + /// JavaScript must wrap the pointer with `__construct()` to create a managed reference + /// that will be cleaned up via FinalizationRegistry. + /// + /// - Returns: A tuple containing presence flag (0 for nil, 1 for some) and retained pointer + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameterWithRetain() -> ( + isSome: Int32, pointer: UnsafeMutableRawPointer + ) { + switch consume self { + case .none: + return (isSome: 0, pointer: UnsafeMutableRawPointer(bitPattern: 1)!) + case .some(let value): + return (isSome: 1, pointer: Unmanaged.passRetained(value).toOpaque()) + } + } + + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ pointer: UnsafeMutableRawPointer) -> Wrapped? + { + if pointer == UnsafeMutableRawPointer(bitPattern: 0) { + return nil + } else { + return Wrapped.bridgeJSLiftReturn(pointer) + } + } + + // MARK: ExportSwift + + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter( + _ isSome: Int32, + _ pointer: UnsafeMutableRawPointer + ) -> Optional { + _bridgeJSLiftParameter(isSome, pointer, liftWrapped: Wrapped.bridgeJSLiftParameter) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Wrapped? { + let isSome = _swift_js_pop_i32() + let pointer = _swift_js_pop_pointer() + return bridgeJSLiftParameter(isSome, pointer) + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Wrapped? { + let pointer = _swift_js_get_optional_heap_object_pointer() + if pointer == UnsafeMutableRawPointer(bitPattern: 0) { + return nil + } else { + return Wrapped.bridgeJSLiftReturn(pointer) + } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + switch consume self { + case .none: + _swift_js_return_optional_heap_object(0, nil) + case .some(let value): + let retainedPointer: UnsafeMutableRawPointer = value.bridgeJSLowerReturn() + _swift_js_return_optional_heap_object(1, retainedPointer) + } + } +} +/// Optional support for case enums +extension Optional where Wrapped: _BridgedSwiftCaseEnum { + // MARK: ExportSwift + + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { + _bridgeJSLowerParameter(noneValue: 0, lowerWrapped: { $0.bridgeJSLowerParameter() }) + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Wrapped? { + _bridgeJSLiftParameter(isSome, wrappedValue, liftWrapped: Wrapped.bridgeJSLiftParameter) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Wrapped? { + let isSome = _swift_js_pop_i32() + let wrappedValue = _swift_js_pop_i32() + return bridgeJSLiftParameter(isSome, wrappedValue) + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ value: Int32) -> Wrapped? { + if value == -1 { + return nil + } else { + return Wrapped.bridgeJSLiftReturn(value) + } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + _bridgeJSLowerReturn( + noneValue: 0, + lowerWrapped: { $0.bridgeJSLowerReturn() }, + write: _swift_js_return_optional_int + ) + } +} + +public protocol _BridgedSwiftTypeLoweredIntoVoidType { + // MARK: ExportSwift + consuming func bridgeJSLowerReturn() -> Void +} + +// MARK: Optional Raw Value Enum Support + +extension Optional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == String { + // MARK: ExportSwift + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> ( + isSome: Int32, value: Int32 + ) { + switch consume self { + case .none: + return (isSome: 0, value: 0) + case .some(let wrapped): + return (isSome: 1, value: wrapped.bridgeJSLowerParameter()) + } + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter( + _ isSome: Int32, + _ bytes: Int32, + _ count: Int32 + ) -> Wrapped? { + let optionalRawValue = String?.bridgeJSLiftParameter(isSome, bytes, count) + return optionalRawValue.flatMap { Wrapped(rawValue: $0) } + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Wrapped? { + let length = _swift_js_get_optional_string() + if length < 0 { + return nil + } else { + let rawValue = String.bridgeJSLiftReturn(length) + return Wrapped(rawValue: rawValue) + } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + let optionalRawValue: String? = self?.rawValue + optionalRawValue.bridgeJSLowerReturn() + } + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Wrapped? { + let isSome = _swift_js_pop_i32() + let bytes = _swift_js_pop_i32() + let count = _swift_js_pop_i32() + return bridgeJSLiftParameter(isSome, bytes, count) + } +} + +extension Optional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == Int { + // MARK: ExportSwift + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { + switch consume self { + case .none: + return (isSome: 0, value: 0) + case .some(let value): + return (isSome: 1, value: value.bridgeJSLowerParameter()) + } + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Wrapped? { + let optionalRawValue = Int?.bridgeJSLiftParameter(isSome, wrappedValue) + return optionalRawValue.flatMap { Wrapped(rawValue: $0) } + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Wrapped? { + let isSome = _swift_js_pop_i32() + let wrappedValue = _swift_js_pop_i32() + return bridgeJSLiftParameter(isSome, wrappedValue) + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Wrapped? { + let isSome = _swift_js_get_optional_int_presence() + if isSome == 0 { + return nil + } else { + let rawValue = _swift_js_get_optional_int_value() + return Wrapped(rawValue: Int(rawValue)) + } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + let optionalRawValue: Int? = self?.rawValue + optionalRawValue.bridgeJSLowerReturn() + } +} + +extension Optional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == Bool { + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Wrapped? { + let optionalRawValue = Bool?.bridgeJSLiftParameter(isSome, wrappedValue) + return optionalRawValue.flatMap { Wrapped(rawValue: $0) } + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Wrapped? { + let isSome = _swift_js_pop_i32() + let wrappedValue = _swift_js_pop_i32() + return bridgeJSLiftParameter(isSome, wrappedValue) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + let optionalRawValue: Bool? = self?.rawValue + optionalRawValue.bridgeJSLowerReturn() + } +} + +extension Optional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == Float { + // MARK: ExportSwift + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> ( + isSome: Int32, value: Float32 + ) { + switch consume self { + case .none: + return (isSome: 0, value: 0.0) + case .some(let wrapped): + return (isSome: 1, value: wrapped.bridgeJSLowerParameter()) + } + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Float32) -> Wrapped? { + let optionalRawValue = Float?.bridgeJSLiftParameter(isSome, wrappedValue) + return optionalRawValue.flatMap { Wrapped(rawValue: $0) } + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Wrapped? { + let isSome = _swift_js_pop_i32() + let wrappedValue = _swift_js_pop_f32() + return bridgeJSLiftParameter(isSome, wrappedValue) + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Wrapped? { + let isSome = _swift_js_get_optional_float_presence() + if isSome == 0 { + return nil + } else { + let rawValue = _swift_js_get_optional_float_value() + return Wrapped(rawValue: Float(rawValue)) + } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + let optionalRawValue: Float? = self?.rawValue + optionalRawValue.bridgeJSLowerReturn() + } +} + +extension Optional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == Double { + // MARK: ExportSwift + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> ( + isSome: Int32, value: Float64 + ) { + switch consume self { + case .none: + return (isSome: 0, value: 0.0) + case .some(let wrapped): + return (isSome: 1, value: wrapped.bridgeJSLowerParameter()) + } + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Float64) -> Wrapped? { + let optionalRawValue = Double?.bridgeJSLiftParameter(isSome, wrappedValue) + return optionalRawValue.flatMap { Wrapped(rawValue: $0) } + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Wrapped? { + let isSome = _swift_js_pop_i32() + let wrappedValue = _swift_js_pop_f64() + return bridgeJSLiftParameter(isSome, wrappedValue) + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Wrapped? { + let isSome = _swift_js_get_optional_double_presence() + if isSome == 0 { + return nil + } else { + let rawValue = _swift_js_get_optional_double_value() + return Wrapped(rawValue: Double(rawValue)) + } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + let optionalRawValue: Double? = self?.rawValue + optionalRawValue.bridgeJSLowerReturn() + } +} + +// MARK: Optional Associated Value Enum Support + +extension Optional where Wrapped: _BridgedSwiftAssociatedValueEnum { + private static func bridgeJSStackPopPayload(_ discriminant: Int32) -> Wrapped? { + if discriminant == -1 { + return nil + } else { + return Wrapped.bridgeJSStackPopPayload(discriminant) + } + } + private consuming func bridgeJSStackPushPayload() -> Int32 { + switch consume self { + case .none: + return -1 + case .some(let value): + return value.bridgeJSStackPushPayload() + } + } + + // MARK: ExportSwift + + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, caseId: Int32) { + switch consume self { + case .none: + return (isSome: 0, caseId: 0) + case .some(let value): + return (isSome: 1, caseId: value.bridgeJSLowerParameter()) + } + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ caseId: Int32) -> Wrapped? { + if isSome == 0 { + return nil + } else { + return Wrapped.bridgeJSLiftParameter(caseId) + } + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ caseId: Int32) -> Wrapped? { + return bridgeJSStackPopPayload(caseId) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() { + bridgeJSStackPush() + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Wrapped? { + let isSome = _swift_js_pop_i32() + let caseId = _swift_js_pop_i32() + return bridgeJSLiftParameter(isSome, caseId) + } + + @_spi(BridgeJS) public consuming func bridgeJSStackPush() -> Void { + switch consume self { + case .none: + _swift_js_push_i32(-1) // Use -1 as sentinel for null + case .some(let value): + value.bridgeJSStackPush() + } + } +} + +// MARK: Optional Struct Support + +extension Optional where Wrapped: _BridgedSwiftStruct { + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32) -> Wrapped? { + if isSome == 0 { + return nil + } else { + return Wrapped.bridgeJSStackPop() + } + } + @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Wrapped? { + return bridgeJSStackPop() + } +} + +// MARK: - Generic Optional Stack Support + +/// Marker protocol for types whose Optional wrapper should use the generic +/// stack-based ABI (`_BridgedSwiftStackType`). Only Array, Dictionary, and +/// `_BridgedSwiftStruct` conform. Primitives and other types keep their +/// own type-specific Optional extensions. +public protocol _BridgedSwiftGenericOptionalStackType: _BridgedSwiftStackType +where StackLiftResult == Self {} + +extension Optional: _BridgedSwiftStackType +where Wrapped: _BridgedSwiftGenericOptionalStackType { + public typealias StackLiftResult = Wrapped? + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Wrapped? { + let isSome = _swift_js_pop_i32() + if isSome == 0 { + return nil + } + return Wrapped.bridgeJSStackPop() + } + + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + switch consume self { + case .none: + _swift_js_push_i32(0) + case .some(let value): + value.bridgeJSStackPush() + _swift_js_push_i32(1) + } + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Wrapped? { + return bridgeJSStackPop() + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + bridgeJSStackPush() + } +} + +// MARK: - _BridgedAsOptional (JSUndefinedOr) delegating to Optional + +extension _BridgedAsOptional where Wrapped: _BridgedSwiftOptionalScalarBridge { + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> ( + isSome: Int32, value: Wrapped.WasmCoreType + ) { + asOptional.bridgeJSLowerParameter() + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter( + _ isSome: Int32, + _ wrappedValue: Wrapped.WasmCoreType + ) -> Self { + Self(optional: Optional.bridgeJSLiftParameter(isSome, wrappedValue)) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + Self(optional: Optional.bridgeJSStackPop()) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + asOptional.bridgeJSLowerReturn() + } +} + +extension _BridgedAsOptional where Wrapped: _BridgedSwiftOptionalScalarSideChannelBridge { + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self { + Self(optional: Optional.bridgeJSLiftReturnFromSideChannel()) + } +} + +extension _BridgedAsOptional where Wrapped == Bool { + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ value: Int32) -> Self { + Self(optional: Optional.bridgeJSLiftReturn(value)) + } +} + +extension _BridgedAsOptional where Wrapped == String { + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { + asOptional.bridgeJSLowerParameter() + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter( + _ isSome: Int32, + _ bytes: Int32, + _ count: Int32 + ) -> Self { + Self(optional: Optional.bridgeJSLiftParameter(isSome, bytes, count)) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + Self(optional: Optional.bridgeJSStackPop()) + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self { + Self(optional: Optional.bridgeJSLiftReturnFromSideChannel()) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + asOptional.bridgeJSLowerReturn() + } +} + +extension _BridgedAsOptional where Wrapped == JSObject { + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { + asOptional.bridgeJSLowerParameter() + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ objectId: Int32) -> Self { + Self(optional: Optional.bridgeJSLiftParameter(isSome, objectId)) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + Self(optional: Optional.bridgeJSStackPop()) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + asOptional.bridgeJSLowerReturn() + } +} + +extension _BridgedAsOptional where Wrapped: _BridgedSwiftProtocolWrapper { + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ objectId: Int32) -> Self { + Self(optional: Optional.bridgeJSLiftParameter(isSome, objectId)) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + asOptional.bridgeJSLowerReturn() + } +} + +extension _BridgedAsOptional where Wrapped: _BridgedSwiftHeapObject { + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, pointer: UnsafeMutableRawPointer) + { + asOptional.bridgeJSLowerParameter() + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerParameterWithRetain() -> ( + isSome: Int32, pointer: UnsafeMutableRawPointer + ) { + asOptional.bridgeJSLowerParameterWithRetain() + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter( + _ isSome: Int32, + _ pointer: UnsafeMutableRawPointer + ) -> Self { + Self(optional: Optional.bridgeJSLiftParameter(isSome, pointer)) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + Self(optional: Optional.bridgeJSStackPop()) + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self { + Self(optional: Optional.bridgeJSLiftReturnFromSideChannel()) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + asOptional.bridgeJSLowerReturn() + } +} + +extension _BridgedAsOptional where Wrapped: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { + asOptional.bridgeJSLowerParameter() + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ caseId: Int32) -> Self { + Self(optional: Optional.bridgeJSLiftParameter(isSome, caseId)) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + Self(optional: Optional.bridgeJSStackPop()) + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ caseId: Int32) -> Self { + Self(optional: Optional.bridgeJSLiftReturn(caseId)) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + asOptional.bridgeJSLowerReturn() + } +} + +extension _BridgedAsOptional +where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == String { + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { + asOptional.bridgeJSLowerParameter() + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter( + _ isSome: Int32, + _ bytes: Int32, + _ count: Int32 + ) -> Self { + Self(optional: Optional.bridgeJSLiftParameter(isSome, bytes, count)) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + Self(optional: Optional.bridgeJSStackPop()) + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self { + Self(optional: Optional.bridgeJSLiftReturnFromSideChannel()) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + asOptional.bridgeJSLowerReturn() + } +} + +extension _BridgedAsOptional +where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == Int { + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { + asOptional.bridgeJSLowerParameter() + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Self { + Self(optional: Optional.bridgeJSLiftParameter(isSome, wrappedValue)) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + Self(optional: Optional.bridgeJSStackPop()) + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self { + Self(optional: Optional.bridgeJSLiftReturnFromSideChannel()) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + asOptional.bridgeJSLowerReturn() + } +} + +extension _BridgedAsOptional +where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == Bool { + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Self { + Self(optional: Optional.bridgeJSLiftParameter(isSome, wrappedValue)) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + Self(optional: Optional.bridgeJSStackPop()) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + asOptional.bridgeJSLowerReturn() + } +} + +extension _BridgedAsOptional +where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == Float { + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Float32) { + asOptional.bridgeJSLowerParameter() + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Float32) -> Self { + Self(optional: Optional.bridgeJSLiftParameter(isSome, wrappedValue)) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + Self(optional: Optional.bridgeJSStackPop()) + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self { + Self(optional: Optional.bridgeJSLiftReturnFromSideChannel()) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + asOptional.bridgeJSLowerReturn() + } +} + +extension _BridgedAsOptional +where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == Double { + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Float64) { + asOptional.bridgeJSLowerParameter() + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Float64) -> Self { + Self(optional: Optional.bridgeJSLiftParameter(isSome, wrappedValue)) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + Self(optional: Optional.bridgeJSStackPop()) + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self { + Self(optional: Optional.bridgeJSLiftReturnFromSideChannel()) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + asOptional.bridgeJSLowerReturn() + } +} + +extension _BridgedAsOptional where Wrapped: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, caseId: Int32) { + asOptional.bridgeJSLowerParameter() + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ caseId: Int32) -> Self { + Self(optional: Optional.bridgeJSLiftParameter(isSome, caseId)) + } + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + Self(optional: Optional.bridgeJSStackPop()) + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ caseId: Int32) -> Self { + Self(optional: Optional.bridgeJSLiftReturn(caseId)) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() { + asOptional.bridgeJSLowerReturn() + } +} + +extension _BridgedAsOptional where Wrapped: _BridgedSwiftStruct { + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32) -> Self { + Self(optional: Optional.bridgeJSLiftParameter(isSome)) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + asOptional.bridgeJSLowerReturn() + } + + // MARK: Stack ABI + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + Self(optional: Optional.bridgeJSStackPop()) + } + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + asOptional.bridgeJSStackPush() + } +} + +// MARK: - Array Support + +extension Array: _BridgedSwiftGenericOptionalStackType +where Element: _BridgedSwiftStackType, Element.StackLiftResult == Element {} +extension Array: _BridgedSwiftStackType where Element: _BridgedSwiftStackType, Element.StackLiftResult == Element { + public typealias StackLiftResult = [Element] + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> [Element] { + let count = Int(_swift_js_pop_i32()) + var result: [Element] = [] + result.reserveCapacity(count) + for _ in 0.. [Element] { + bridgeJSStackPop() + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() { + self.bridgeJSStackPush() + } + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() { + self.bridgeJSStackPush() + } + @_spi(BridgeJS) public static func bridgeJSLiftReturn() -> [Element] { + bridgeJSStackPop() + } +} + +// MARK: - Dictionary Support + +public protocol _BridgedSwiftDictionaryStackType: _BridgedSwiftTypeLoweredIntoVoidType, + _BridgedSwiftGenericOptionalStackType +{ + associatedtype DictionaryValue: _BridgedSwiftStackType + where DictionaryValue.StackLiftResult == DictionaryValue +} + +extension Dictionary: _BridgedSwiftGenericOptionalStackType +where Key == String, Value: _BridgedSwiftStackType, Value.StackLiftResult == Value {} +extension Dictionary: _BridgedSwiftStackType +where Key == String, Value: _BridgedSwiftStackType, Value.StackLiftResult == Value { + public typealias StackLiftResult = [String: Value] + // Lowering/return use stack-based encoding, so dictionary also behaves like a void-lowered type. + // Optional/JSUndefinedOr wrappers rely on this conformance to push an isSome flag and + // then delegate to the stack-based lowering defined below. + // swiftlint:disable:next type_name +} + +extension Dictionary: _BridgedSwiftTypeLoweredIntoVoidType, _BridgedSwiftDictionaryStackType +where Key == String, Value: _BridgedSwiftStackType, Value.StackLiftResult == Value { + public typealias DictionaryValue = Value + + @_spi(BridgeJS) public static func bridgeJSStackPop() -> [String: Value] { + let count = Int(_swift_js_pop_i32()) + var result: [String: Value] = [:] + result.reserveCapacity(count) + for _ in 0.. [String: Value] { + bridgeJSStackPop() + } + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() { + self.bridgeJSStackPush() + } + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() { + self.bridgeJSStackPush() + } + @_spi(BridgeJS) public static func bridgeJSLiftReturn() -> [String: Value] { + bridgeJSStackPop() + } +} + +extension Optional where Wrapped: _BridgedSwiftDictionaryStackType { + typealias DictionaryValue = Wrapped.DictionaryValue + + private consuming func bridgeJSStackPushPayload() -> Int32 { + switch consume self { + case .none: + return 0 + case .some(let dict): + dict.bridgeJSStackPush() + return 1 + } + } + private static func bridgeJSStackPopPayload(_ isSome: Int32) -> [String: Wrapped.DictionaryValue]? { + if isSome == 0 { + return nil + } + return Dictionary.bridgeJSStackPop() + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSStackPushPayload() + } + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32) -> [String: Wrapped.DictionaryValue]? { + return bridgeJSStackPopPayload(isSome) + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturn() -> [String: Wrapped.DictionaryValue]? { + return bridgeJSStackPopPayload(_swift_js_pop_i32()) + } +} + +extension _BridgedAsOptional where Wrapped: _BridgedSwiftDictionaryStackType { + typealias DictionaryValue = Wrapped.DictionaryValue + + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Int32 { + let opt = asOptional + if let dict = opt { + dict.bridgeJSLowerReturn() + return 1 + } + return 0 + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturn() -> Self { + let isSome = _swift_js_pop_i32() + if isSome == 0 { + return Self(optional: nil) + } + let value = Dictionary.bridgeJSLiftParameter() as! Wrapped + return Self(optional: value) + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + asOptional.bridgeJSLowerReturn() + } +} diff --git a/Sources/JavaScriptKit/ConvertibleToJSValue.swift b/Sources/JavaScriptKit/ConvertibleToJSValue.swift index afa632745..3f548a46c 100644 --- a/Sources/JavaScriptKit/ConvertibleToJSValue.swift +++ b/Sources/JavaScriptKit/ConvertibleToJSValue.swift @@ -79,15 +79,12 @@ extension JSString: ConvertibleToJSValue { public var jsValue: JSValue { .string(self) } } -extension JSObject: JSValueCompatible { - // `JSObject.jsValue` is defined in JSObject.swift to be able to overridden - // from `JSFunction` -} +extension JSObject: JSValueCompatible {} -private let _objectConstructor = LazyThreadLocal(initialize: { JSObject.global.Object.function! }) -private var objectConstructor: JSFunction { _objectConstructor.wrappedValue } -private let _arrayConstructor = LazyThreadLocal(initialize: { JSObject.global.Array.function! }) -private var arrayConstructor: JSFunction { _arrayConstructor.wrappedValue } +private let _objectConstructor = LazyThreadLocal(initialize: { JSObject.global.Object.object! }) +private var objectConstructor: JSObject { _objectConstructor.wrappedValue } +private let _arrayConstructor = LazyThreadLocal(initialize: { JSObject.global.Array.object! }) +private var arrayConstructor: JSObject { _arrayConstructor.wrappedValue } #if !hasFeature(Embedded) extension Dictionary where Value == ConvertibleToJSValue, Key == String { @@ -177,7 +174,7 @@ extension Array: ConstructibleFromJSValue where Element: ConstructibleFromJSValu public static func construct(from value: JSValue) -> [Element]? { guard let objectRef = value.object, - objectRef.isInstanceOf(JSObject.global.Array.function!) + objectRef.isInstanceOf(JSObject.global.Array.object!) else { return nil } let count: Int = objectRef.length.fromJSValue()! @@ -208,8 +205,6 @@ extension RawJSValue: ConvertibleToJSValue { return .null case .undefined: return .undefined - case .function: - return .function(JSFunction(id: UInt32(payload1))) case .symbol: return .symbol(JSSymbol(id: UInt32(payload1))) case .bigInt: @@ -227,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 @@ -248,9 +243,6 @@ extension JSValue { case .undefined: kind = .undefined payload1 = 0 - case .function(let functionRef): - kind = .function - payload1 = JavaScriptPayload1(functionRef.id) case .symbol(let symbolRef): kind = .symbol payload1 = JavaScriptPayload1(symbolRef.id) diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Ahead-of-Time-Code-Generation.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Ahead-of-Time-Code-Generation.md index e3f52885c..776f6f577 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Ahead-of-Time-Code-Generation.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Ahead-of-Time-Code-Generation.md @@ -6,7 +6,7 @@ Learn how to improve build times by generating BridgeJS code ahead of time. > Important: This feature is still experimental. No API stability is guaranteed, and the API may change in future releases. -The BridgeJS build plugin automatically processes `@JS` annotations and TypeScript definitions during each build. While convenient, this can significantly increase build times for larger projects. To address this, JavaScriptKit provides a command plugin that lets you generate the bridge code ahead of time. +The BridgeJS build plugin automatically processes macro annotations and TypeScript definitions during each build. While convenient, this can significantly increase build times for larger projects. To address this, JavaScriptKit provides a command plugin that lets you generate the bridge code ahead of time. ## Using the Command Plugin @@ -54,7 +54,7 @@ $ echo "{}" > Sources/MyApp/bridge-js.config.json ### Step 3: Create Your Swift Code with @JS Annotations -Write your Swift code with `@JS` annotations as usual: +Write your Swift code with macro annotations as usual: ```swift import JavaScriptKit @@ -65,13 +65,13 @@ import JavaScriptKit @JS class Counter { private var count = 0 - + @JS init() {} - + @JS func increment() { count += 1 } - + @JS func getValue() -> Int { return count } @@ -104,16 +104,16 @@ swift package plugin bridge-js This command will: -1. Process all Swift files with `@JS` annotations +1. Process all Swift files with macro annotations 2. Process any TypeScript definition files 3. Generate Swift binding code in a `Generated` directory within your source folder For example, with a target named "MyApp", it will create: ``` -Sources/MyApp/Generated/ExportSwift.swift # Generated code for Swift exports -Sources/MyApp/Generated/ImportTS.swift # Generated code for TypeScript imports -Sources/MyApp/Generated/JavaScript/ # Generated JSON skeletons +Sources/MyApp/Generated/BridgeJS.swift # Glue code for both exports and imports +Sources/MyApp/Generated/BridgeJS.Macros.swift # Bridging interface generated from bridge-js.d.ts +Sources/MyApp/Generated/JavaScript/BridgeJS.json # Unified skeleton JSON ``` ### Step 6: Add Generated Files to Version Control @@ -174,4 +174,4 @@ git commit -m "Update generated BridgeJS code" 2. **Version Control**: Always commit the generated files if using the command plugin 3. **API Boundaries**: Try to stabilize your API boundaries to minimize regeneration 4. **Documentation**: Document your approach in your project README -5. **CI/CD**: If using the command plugin, consider verifying that generated code is up-to-date in CI +5. **CI/CD**: If using the command plugin, consider verifying that generated code is up-to-date in CI diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Configuration.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Configuration.md index 835cf6bef..604017aad 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Configuration.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Configuration.md @@ -38,14 +38,51 @@ Later files override settings from earlier files. This allows teams to commit a ## Configuration Options +### `exposeToGlobal` + +Controls whether exported Swift APIs are exposed to the JavaScript global namespace (`globalThis`). + +When `true`, exported functions, classes, and namespaces are available via `globalThis` in JavaScript. When `false`, they are only available through the exports object returned by `createExports()`. +Using Exports provides better module isolation and support multiple WebAssembly instances in the same JavaScript context. + +Example: + +```json +{ + "exposeToGlobal": true +} +``` + +**With `exposeToGlobal: true`:** + +```javascript +// APIs available on globalThis +const greeter = new globalThis.MyModule.Greeter("World"); +console.log(greeter.greet()); // "Hello, World!" + +// Also available via exports +const greeter2 = new exports.MyModule.Greeter("Alice"); +``` + +**With `exposeToGlobal: false` (default):** + +```javascript +// APIs only available via exports +const greeter = new exports.MyModule.Greeter("World"); + +// globalThis.MyModule is undefined +``` + ### `tools` Specify custom paths for external executables. This is particularly useful when working in environments like Xcode where the system PATH may not be inherited, or when you need to use a specific version of tools for your project. Currently supported tools: + - `node` - Node.js runtime (required for TypeScript processing) Example: + ```json { "tools": { @@ -59,4 +96,3 @@ BridgeJS resolves tool paths in the following priority order: 1. **Configuration files** (`bridge-js.config.local.json` > `bridge-js.config.json`) 2. **Environment variables** (`JAVASCRIPTKIT_NODE_EXEC`) 3. **System PATH lookup** - diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Internals/BridgeJS-Internals.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Internals/BridgeJS-Internals.md new file mode 100644 index 000000000..b8589b49e --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Internals/BridgeJS-Internals.md @@ -0,0 +1,11 @@ +# BridgeJS Internals + +Internal design, performance rationale, and low-level details for BridgeJS. + +## Overview + +This section is for maintainers and contributors who want to understand how BridgeJS works under the hood, why it is designed the way it is, and how it interacts with the JavaScript engine and ABI. + +## Topics + +- diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Internals/Design-Rationale.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Internals/Design-Rationale.md new file mode 100644 index 000000000..8bfc5d302 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Internals/Design-Rationale.md @@ -0,0 +1,38 @@ +# BridgeJS Design Rationale + +Why BridgeJS is faster than dynamic `JSObject`/`JSValue` APIs and how engine optimizations influence the design. + +## Overview + +BridgeJS generates **specialized** bridge code per exported or imported interface. That specialization, combined with stable call and property access patterns, allows JavaScript engines to optimize the boundary crossing much better than with generic dynamic code. This page explains the main performance rationale. + +## Why generated code is faster + +1. **Specialized code per interface** - Each bridged function or property gets its own glue path with known types. The engine does not need to handle arbitrary shapes or types at the call site. + +2. **Use of static type information** - The generator knows parameter and return types at compile time. It can avoid dynamic type checks and boxing where the dynamic API would require them. + +3. **IC-friendly access patterns** - Property and method accesses use stable, predictable shapes instead of a single generic subscript path. That keeps engine **inline caches (ICs)** effective instead of turning them **megamorphic**. + +## Inline caches (ICs) and megamorphic penalty + +JavaScript engines (and many other dynamic-language VMs) use **inline caches** at property and method access sites: they remember the object shape (e.g. “this property is at offset X”) so the next access with the same shape can take a fast path. + +- **Monomorphic** - One shape seen at a site → very fast, offset cached. +- **Polymorphic** - A few shapes → still fast, small dispatch in the IC. +- **Megamorphic** - Too many different shapes at the same site → the IC gives up and falls back to a generic property lookup, which is much slower. + +Engines typically allow only a small number of shapes per IC (e.g. on the order of a few) before marking the site megamorphic. + +## Why `JSObject` subscript is problematic + +`JSObject.subscript` (and similar dynamic property access) shares **one** code path for all property names and all object shapes. Every access goes through the same call site with varying keys and receiver shapes. That site therefore sees many different shapes and quickly becomes **megamorphic**, so the engine cannot cache property offsets and must do a generic lookup every time. + +So even if you cache the property name (e.g. with `CachedJSStrings`), you are still using the same generic subscript path; the call site stays megamorphic and pays the slow-path cost. + +BridgeJS avoids this by generating **separate** access paths per property or method. Each generated getter/setter or function call has a stable shape at the engine level, so the IC can stay monomorphic or polymorphic and the fast path is used. + +## What to read next + +- ABI and binary interface details will be documented in this section as they stabilize. +- For using BridgeJS in your app, see , , and . diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Bringing-Swift-Closures-to-JavaScript.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Bringing-Swift-Closures-to-JavaScript.md new file mode 100644 index 000000000..ce1d9d555 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Bringing-Swift-Closures-to-JavaScript.md @@ -0,0 +1,80 @@ +# Bringing Swift Closures to JavaScript + +Use ``JSTypedClosure`` to pass or return Swift closures to the JavaScript world with BridgeJS-with type safety and explicit lifetime management. + +## Overview + +``JSTypedClosure`` wraps a **Swift closure** so you can **pass it or return it to JavaScript** through BridgeJS. The closure lives in Swift; JavaScript receives a function that calls back into that closure when invoked. Use it when: + +- You **pass** a Swift closure as an argument to a JavaScript API (e.g. an ``JSFunction(jsName:from:)`` that takes a callback parameter). +- You **return** a Swift closure from Swift exported by ``JS(namespace:enumStyle:)`` so JavaScript can call it later. + +Unlike ``JSClosure``, which uses untyped ``JSValue`` arguments and return values, ``JSTypedClosure`` has a concrete **signature** (e.g. `(Int) -> Int` or `(String) -> Void`). BridgeJS generates the glue code for that signature, so you get compile-time type safety when crossing into the JS world. + +You **must call** ``JSTypedClosure/release()`` when the closure is no longer needed by JavaScript. After release, any attempt to invoke the closure from JavaScript throws an explicit JS exception. + +## Creating a JSTypedClosure + +BridgeJS generates an initializer for each closure signature used in your module. Wrap your Swift closure and pass or return it to JavaScript: + +```swift +import JavaScriptKit + +// Pass a Swift closure to a JS function that expects a callback (Int) -> Int +@JSFunction static func applyTransform(_ value: Int, _ transform: JSTypedClosure<(Int) -> Int>) throws(JSException) -> Int + +let double = JSTypedClosure<(Int) -> Int> { $0 * 2 } +defer { double.release() } +let result = try applyTransform(10, double) // 20 - JS calls back into Swift +``` + +You can pass or return typed closures with other signatures the same way: + +```swift +let sum = JSTypedClosure<(Int, Int) -> Int> { $0 + $1 } +defer { sum.release() } + +let log = JSTypedClosure<(String) -> Void> { print($0) } +defer { log.release() } +``` + +## Lifetime and release() + +A ``JSTypedClosure`` keeps the Swift closure alive and exposes a JavaScript function that calls into it. To avoid leaks and use-after-free: + +1. **Call `release()` exactly once** when the closure is no longer needed by JavaScript (e.g. when the callback is unregistered or the object that held it is released). +2. Prefer **`defer { closure.release() }`** right after creating the closure so cleanup runs when the current scope exits. +3. After `release()`, calling the closure from JavaScript throws an exception with a message that includes the file and line where the ``JSTypedClosure`` was created. + +A **FinalizationRegistry** on the JavaScript side may eventually release the Swift storage if you never call `release()`, but that is non-deterministic. Do not rely on it for timely cleanup. + +## Getting the underlying JavaScript function + +When you need to store or pass the function on the JavaScript side (e.g. to compare identity or attach to a DOM node), use the ``JSTypedClosure/jsObject`` property to get the ``JSObject`` that represents the JavaScript function. + +## JSTypedClosure vs JSClosure + +Both let you pass or return a Swift closure to the JavaScript world. The difference is how they are typed and which API you use: + +| | JSTypedClosure | JSClosure | +|:--|:--|:--| +| **API** | BridgeJS (macros, generated code) | Dynamic ``JSObject`` / ``JSValue`` | +| **Types** | Typed signature, e.g. `(Int) -> Int` | Untyped `([JSValue]) -> JSValue` | +| **Lifetime** | Explicit `release()` required | Explicit `release()` required | +| **Use case** | Passing/returning closures at the BridgeJS boundary with a fixed signature | Passing Swift functions to JS via dynamic APIs (e.g. DOM events) | + +Use ``JSTypedClosure`` when you pass or return closures through BridgeJS-declared APIs. Use ``JSClosure`` when you pass a Swift function to JavaScript using the dynamic APIs (e.g. ``JSObject``, ``JSValue``) without generated glue. + +## JSTypedClosure vs auto-managed closures + +BridgeJS can also expose **plain** Swift closure types (e.g. `(String) -> String`) as parameters and return values; lifetime is then managed automatically via ``FinalizationRegistry`` and no `release()` is required. See . + +**When returning** a closure from Swift to JavaScript, we **recommend** using ``JSTypedClosure`` and managing lifetime explicitly with `release()`, rather than returning a plain closure type. Explicit release makes cleanup predictable and avoids relying solely on JavaScript GC. + +## See also + +- ``JSTypedClosure`` +- ``JSClosure`` +- +- +- diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md index 6ce307721..b14d2eebe 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md @@ -6,249 +6,27 @@ Learn how to make your Swift code callable from JavaScript. > Important: This feature is still experimental. No API stability is guaranteed, and the API may change in future releases. -BridgeJS allows you to expose Swift functions, classes, and methods to JavaScript by using the `@JS` attribute. This enables JavaScript code to call into Swift code running in WebAssembly. +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). -## Configuring the BridgeJS plugin +BridgeJS allows you to expose Swift functions, classes, and methods to JavaScript by using the ``JS(namespace:enumStyle:)`` attribute. This enables JavaScript code to call into Swift code running in WebAssembly. -To use the BridgeJS feature, you need to enable the experimental `Extern` feature and add the BridgeJS plugin to your package. Here's an example of a `Package.swift` file: +Configure your package and build for JavaScript as described in . Then use the topics below to expose Swift types and functions to JavaScript. -```swift -// swift-tools-version:6.0 +## Topics -import PackageDescription +- +- +- +- +- +- +- +- +- +- +- +- -let package = Package( - name: "MyApp", - dependencies: [ - .package(url: "https://github.com/swiftwasm/JavaScriptKit.git", branch: "main") - ], - targets: [ - .executableTarget( - name: "MyApp", - dependencies: ["JavaScriptKit"], - swiftSettings: [ - // This is required because the generated code depends on @_extern(wasm) - .enableExperimentalFeature("Extern") - ], - plugins: [ - // Add build plugin for processing @JS and generate Swift glue code - .plugin(name: "BridgeJS", package: "JavaScriptKit") - ] - ) - ] -) -``` +## See Also -The `BridgeJS` plugin will process your Swift code to find declarations marked with `@JS` and generate the necessary bridge code to make them accessible from JavaScript. - -### Building your package for JavaScript - -After configuring your `Package.swift`, you can build your package for JavaScript using the following command: - -```bash -swift package --swift-sdk $SWIFT_SDK_ID js -``` - -This command will: -1. Process all Swift files with `@JS` annotations -2. Generate JavaScript bindings and TypeScript type definitions (`.d.ts`) for your exported Swift code -4. Output everything to the `.build/plugins/PackageToJS/outputs/` directory - -> Note: For larger projects, you may want to generate the BridgeJS code ahead of time to improve build performance. See for more information. - -## Marking Swift Code for Export - -### Functions - -To export a Swift function to JavaScript, mark it with the `@JS` attribute and make it `public`: - -```swift -import JavaScriptKit - -@JS public func calculateTotal(price: Double, quantity: Int) -> Double { - return price * Double(quantity) -} - -@JS public func formatCurrency(amount: Double) -> String { - return "$\(String(format: "%.2f", amount))" -} -``` - -These functions will be accessible from JavaScript: - -```javascript -const total = exports.calculateTotal(19.99, 3); -const formattedTotal = exports.formatCurrency(total); -console.log(formattedTotal); // "$59.97" -``` - -The generated TypeScript declarations for these functions would look like: - -```typescript -export type Exports = { - calculateTotal(price: number, quantity: number): number; - formatCurrency(amount: number): string; -} -``` - -### Classes - -To export a Swift class, mark both the class and any members you want to expose: - -```swift -import JavaScriptKit - -@JS class ShoppingCart { - private var items: [(name: String, price: Double, quantity: Int)] = [] - - @JS init() {} - - @JS public func addItem(name: String, price: Double, quantity: Int) { - items.append((name, price, quantity)) - } - - @JS public func removeItem(atIndex index: Int) { - guard index >= 0 && index < items.count else { return } - items.remove(at: index) - } - - @JS public func getTotal() -> Double { - return items.reduce(0) { $0 + $1.price * Double($1.quantity) } - } - - @JS public func getItemCount() -> Int { - return items.count - } - - // This method won't be accessible from JavaScript (no @JS) - var debugDescription: String { - return "Cart with \(items.count) items, total: \(getTotal())" - } -} -``` - -In JavaScript: - -```javascript -import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; -const { exports } = await init({}); - -const cart = new exports.ShoppingCart(); -cart.addItem("Laptop", 999.99, 1); -cart.addItem("Mouse", 24.99, 2); -console.log(`Items in cart: ${cart.getItemCount()}`); -console.log(`Total: $${cart.getTotal().toFixed(2)}`); -``` - -The generated TypeScript declarations for this class would look like: - -```typescript -// Base interface for Swift reference types -export interface SwiftHeapObject { - release(): void; -} - -// ShoppingCart interface with all exported methods -export interface ShoppingCart extends SwiftHeapObject { - addItem(name: string, price: number, quantity: number): void; - removeItem(atIndex: number): void; - getTotal(): number; - getItemCount(): number; -} - -export type Exports = { - ShoppingCart: { - new(): ShoppingCart; - } -} -``` - -## Using Namespaces - -The `@JS` macro supports organizing your exported Swift code into namespaces using dot-separated strings. This allows you to create hierarchical structures in JavaScript that mirror your Swift code organization. - -### Functions with Namespaces - -You can export functions to specific namespaces by providing a namespace parameter: - -```swift -import JavaScriptKit - -// Export a function to a custom namespace -@JS(namespace: "MyModule.Utils") func namespacedFunction() -> String { - return "namespaced" -} -``` - -This function will be accessible in JavaScript through its namespace hierarchy: - -```javascript -// Access the function through its namespace -const result = globalThis.MyModule.Utils.namespacedFunction(); -console.log(result); // "namespaced" -``` - -The generated TypeScript declaration will reflect the namespace structure: - -```typescript -declare global { - namespace MyModule { - namespace Utils { - function namespacedFunction(): string; - } - } -} -``` - -### Classes with Namespaces - -For classes, you only need to specify the namespace on the top-level class declaration. All exported methods within the class will be part of that namespace: - -```swift -import JavaScriptKit - -@JS(namespace: "__Swift.Foundation") class Greeter { - var name: String - - @JS init(name: String) { - self.name = name - } - - @JS func greet() -> String { - return "Hello, " + self.name + "!" - } - - func changeName(name: String) { - self.name = name - } -} -``` - -In JavaScript, this class is accessible through its namespace: - -```javascript -// Create instances through namespaced constructors -const greeter = new globalThis.__Swift.Foundation.Greeter("World"); -console.log(greeter.greet()); // "Hello, World!" -``` - -The generated TypeScript declaration will organize the class within its namespace: - -```typescript -declare global { - namespace __Swift { - namespace Foundation { - class Greeter { - constructor(name: string); - greet(): string; - } - } - } -} - -export interface Greeter extends SwiftHeapObject { - greet(): string; -} -``` - -Using namespaces can be preferable for projects with many global functions, as they help prevent naming collisions. Namespaces also provide intuitive hierarchies for organizing your exported Swift code, and they do not affect the code generated by `@JS` declarations without namespaces. +- ``JS(namespace:enumStyle:)`` diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Array.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Array.md new file mode 100644 index 000000000..e97bceefa --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Array.md @@ -0,0 +1,134 @@ +# 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/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +BridgeJS allows you to pass Swift arrays as function parameters and return values. + +```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) | ✅ | +| `JSObject` arrays: `[JSObject]` | ✅ | +| `@JSClass struct` arrays: `[Foo]` | ✅ | +| 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-Class.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Class.md new file mode 100644 index 000000000..9cd4a2224 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Class.md @@ -0,0 +1,107 @@ +# Exporting Swift Classes to JS + +Learn how to export Swift classes to JavaScript. + +## Overview + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +To export a Swift class, mark both the class and any members you want to expose: + +```swift +import JavaScriptKit + +@JS class ShoppingCart { + private var items: [(name: String, price: Double, quantity: Int)] = [] + + @JS init() {} + + @JS public func addItem(name: String, price: Double, quantity: Int) { + items.append((name, price, quantity)) + } + + @JS public func removeItem(atIndex index: Int) { + guard index >= 0 && index < items.count else { return } + items.remove(at: index) + } + + @JS public func getTotal() -> Double { + return items.reduce(0) { $0 + $1.price * Double($1.quantity) } + } + + @JS public func getItemCount() -> Int { + return items.count + } + + // This method won't be accessible from JavaScript (no @JS) + var debugDescription: String { + return "Cart with \(items.count) items, total: \(getTotal())" + } +} +``` + +In JavaScript: + +```javascript +import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; +const { exports } = await init({}); + +const cart = new exports.ShoppingCart(); +cart.addItem("Laptop", 999.99, 1); +cart.addItem("Mouse", 24.99, 2); +console.log(`Items in cart: ${cart.getItemCount()}`); +console.log(`Total: $${cart.getTotal().toFixed(2)}`); +cart.release(); // Call release() when done; don't rely on FinalizationRegistry as much as possible +``` + +The generated TypeScript declarations for this class would look like: + +```typescript +// Base interface for Swift reference types +export interface SwiftHeapObject { + release(): void; +} + +// ShoppingCart interface with all exported methods +export interface ShoppingCart extends SwiftHeapObject { + addItem(name: string, price: number, quantity: number): void; + removeItem(atIndex: number): void; + getTotal(): number; + getItemCount(): number; +} + +export type Exports = { + ShoppingCart: { + new(): ShoppingCart; + } +} +``` + +## How It Works + +Classes use **reference semantics** when crossing the Swift/JavaScript boundary: + +1. **Object Creation**: When you create a class instance (via `new` in JS), the object lives on the Swift heap +2. **Reference Passing**: JavaScript receives a reference (handle) to the Swift object, not a copy +3. **Shared State**: Changes made through either Swift or JavaScript affect the same object +4. **Memory Management**: `FinalizationRegistry` can release Swift objects when they're garbage collected in JavaScript, but you should **not rely on it** for cleanup. Call `release()` when an instance is no longer needed so that Swift memory is reclaimed deterministically. This is especially important for **short-lived instances**: GC may run late or not at all for objects that become unreachable quickly, so relying on `FinalizationRegistry` can delay or leak Swift-side resources. + +This differs from structs, which use copy semantics and transfer data by value. + +## Supported Features + +| Swift Feature | Status | +|:--------------|:-------| +| Initializers: `init()` | ✅ | +| Initializers that throw JSException: `init() throws(JSException)` | ✅ | +| Initializers that throw any exception: `init() throws` | ❌ | +| Async initializers: `init() async` | ❌ | +| Deinitializers: `deinit` | ✅ | +| Stored properties: `var`, `let` (with `willSet`, `didSet`) | ✅ | +| Computed properties: `var x: X { get set }` | ✅ | +| Computed properties with effects: `var x: X { get async throws }` | 🚧 | +| Static / class properties: `static var`, `class let` | ✅ (See )| +| Methods: `func` | ✅ (See ) | +| Static/class methods: `static func`, `class func` | ✅ (See ) | +| Subscripts: `subscript()` | ❌ | +| Generics | ❌ | diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Closure.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Closure.md new file mode 100644 index 000000000..adb9ab33b --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Closure.md @@ -0,0 +1,121 @@ +# Exporting Swift Closures to JS + +Learn how to use closure/function types as parameters and return values in BridgeJS. + +## Overview + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +BridgeJS supports typed closure parameters and return values, allowing you to pass or return Swift closures to JavaScript with full type safety. **Lifetime is automatic**: you use plain Swift closure types (e.g. `(String) -> String`); the runtime releases them when no longer needed-no manual `release()` required. This enables callbacks, higher-order functions, and function composition across the boundary. + +**Recommendation:** When **returning** a closure from Swift to JavaScript, prefer returning a ``JSTypedClosure`` and managing its lifetime explicitly (see ). Explicit `release()` makes cleanup predictable and avoids relying solely on JavaScript garbage collection. Use plain closure types (this article) when you want fully automatic lifetime or when passing closures only as parameters into your exported API. + +## Example + +```swift +import JavaScriptKit + +@JS class TextProcessor { + private var transform: (String) -> String + + @JS init(transform: @escaping (String) -> String) { + self.transform = transform + } + + @JS func processWithPerson(_ person: Person, formatter: (Person) -> String) -> String { + return formatter(person) + } + + @JS func makePersonCreator(defaultName: String) -> (String) -> Person { + return { name in + let fullName = name.isEmpty ? defaultName : name + return Person(name: fullName) + } + } + + @JS func getTransform() -> (String) -> String { + return transform + } +} +``` + +In JavaScript: + +```javascript +import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; +const { exports } = await init({}); + +// Pass closure to initializer +const processor = new exports.TextProcessor((text) => text.toUpperCase()); +console.log(processor.getTransform()("hello")); // "HELLO" + +// Pass closure with Swift class parameter +const person = new exports.Person("Alice"); +const result = processor.processWithPerson(person, (p) => { + return `${p.name}: ${p.greet()}`; +}); +console.log(result); // "Alice: Hello, Alice!" + +// Call returned closure +const creator = processor.makePersonCreator("Default"); +const p1 = creator("Bob"); +console.log(p1.greet()); // "Hello, Bob!" +p1.release(); + +const p2 = creator(""); // Empty uses default +console.log(p2.greet()); // "Hello, Default!" +p2.release(); + +person.release(); +processor.release(); +``` + +The generated TypeScript declarations: + +```typescript +export interface TextProcessor extends SwiftHeapObject { + processWithPerson( + person: Person, + formatter: (arg0: Person) => string + ): string; + makePersonCreator( + defaultName: string + ): (arg0: string) => Person; + getTransform(): (arg0: string) => string; +} + +export type Exports = { + TextProcessor: { + new(transform: (arg0: string) => string): TextProcessor + }; +} +``` + +## How It Works + +Closures use **reference semantics** when crossing the Swift/JavaScript boundary: + +1. **JavaScript → Swift**: When JavaScript passes a function to Swift, it's stored in `swift.memory` with reference counting. When Swift's closure wrapper is deallocated by ARC, the JavaScript function is released. +2. **Swift → JavaScript**: When Swift returns a closure to JavaScript, the Swift closure is boxed and automatically released when the JavaScript function is garbage collected. +3. **Memory Management**: Both directions use automatic memory management via `FinalizationRegistry` - no manual cleanup required. + +This differs from structs and arrays, which use copy semantics and transfer data by value. + +When you **return** a closure to JavaScript, we recommend using ``JSTypedClosure`` and calling `release()` when the closure is no longer needed, instead of returning a plain closure type. See . + +## Supported Features + +| Swift Feature | Status | +|:--------------|:-------| +| Closure Parameters with Supported Types `(String, Int) -> Person` | ✅ | +| Closure Return Value with Supported Types `() -> Person` | ✅ | +| `@escaping` closures | ✅ | +| Optional types in closures | ✅ | +| Closure-typed `@JS` properties | ❌ | +| Async closures | ❌ | +| Throwing closures | ❌ | + +## See Also + +- - passing or returning closures with ``JSTypedClosure`` and explicit `release()` +- diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Default-Parameters.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Default-Parameters.md new file mode 100644 index 000000000..e6f4b8e9a --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Default-Parameters.md @@ -0,0 +1,164 @@ +# Default Parameters in Exported Swift Functions + +Learn how to use default parameter values in Swift functions and constructors exported to JavaScript. + +## Overview + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +BridgeJS supports default parameter values for Swift functions and class constructors exported to JavaScript. When you specify default values in your Swift code, they are automatically applied in the generated JavaScript bindings. + +```swift +import JavaScriptKit + +@JS public func greet(name: String = "World", enthusiastic: Bool = false) -> String { + let greeting = "Hello, \(name)" + return enthusiastic ? "\(greeting)!" : greeting +} +``` + +In JavaScript, parameters with defaults become optional: + +```javascript +exports.greet(); // "Hello, World" +exports.greet("Alice"); // "Hello, Alice" +exports.greet("Bob", true); // "Hello, Bob!" +``` + +The generated TypeScript definitions show optional parameters with JSDoc comments: + +```typescript +export type Exports = { + /** + * @param name - Optional parameter (default: "World") + * @param enthusiastic - Optional parameter (default: false) + */ + greet(name?: string, enthusiastic?: boolean): string; +} +``` + +## Skipping Parameters With Default Values + +To use a default value for a middle parameter while providing later parameters, pass `undefined`: + +```swift +@JS public func configure(title: String = "Default", count: Int = -10, enabled: Bool = false) -> String { + return "\(title): \(count) (\(enabled))" +} +``` + +```javascript +// Use all defaults +exports.configure(); // "Default: 10 (false)" +exports.configure("Custom"); // "Custom: -10 (false)" +exports.configure("Custom", undefined, true); // "Custom: -10 (true)" +exports.configure("Custom", 5, true); // "Custom: 5 (true)" +``` + +## Default Parameters in Constructors + +Constructor parameters also support default values, making it easy to create instances with flexible initialization options: + +```swift +@JS class Config { + @JS var name: String + @JS var timeout: Int + @JS var retries: Int + + @JS init(name: String = "default", timeout: Int = 30, retries: Int = 3) { + self.name = name + self.timeout = timeout + self.retries = retries + } +} +``` + +In JavaScript, you can omit constructor parameters or use `undefined` to skip them: + +```javascript +const c1 = new exports.Config(); // name: "default", timeout: 30, retries: 3 +const c2 = new exports.Config("custom"); // name: "custom", timeout: 30, retries: 3 +const c3 = new exports.Config("api", 60); // name: "api", timeout: 60, retries: 3 +const c4 = new exports.Config("api", undefined, 5); // name: "api", timeout: 30, retries: 5 +``` + +The generated TypeScript definitions include JSDoc comments for constructor parameters: + +```typescript +/** + * @param name - Optional parameter (default: "default") + * @param timeout - Optional parameter (default: 30) + * @param retries - Optional parameter (default: 3) + */ +new(name?: string, timeout?: number, retries?: number): Config; +``` + +## Supported Default Value Types + +The following default value types are supported for both function and constructor parameters: + +| Default Value Type | Swift Example | JavaScript/TypeScript | +|:-------------------|:-------------|:----------------------| +| String literals | `"hello"` | `"hello"` | +| Integer literals | `42` | `42` | +| Float literals | `3.14` | `3.14` | +| Double literals | `2.718` | `2.718` | +| Boolean literals | `true`, `false` | `true`, `false` | +| Nil for optionals | `nil` | `null` | +| Enum cases (shorthand) | `.north` | `Direction.North` | +| Enum cases (qualified) | `Direction.north` | `Direction.North` | +| 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 + +You can use class or struct initialization expressions as default values: + +```swift +@JS struct Point { + var x: Double + var y: Double +} + +@JS class Config { + var setting: String + @JS init(setting: String) { self.setting = setting } +} + +@JS public func processPoint(point: Point = Point(x: 0.0, y: 0.0)) -> String +@JS public func processConfig(config: Config = Config(setting: "default")) -> String +``` + +In JavaScript, structs become object literals while classes use constructor calls: + +```javascript +exports.processPoint(); // uses default { x: 0.0, y: 0.0 } +exports.processPoint({ x: 5.0, y: 10.0 }); // custom struct + +exports.processConfig(); // uses default new Config("default") +const custom = new exports.Config("custom"); +exports.processConfig(custom); // custom instance +custom.release(); +``` + +**Requirements:** + +- Constructor/initializer arguments must be literal values (`"text"`, `42`, `true`, `false`, `nil`) +- Struct initializers must use labeled arguments (e.g., `Point(x: 1.0, y: 2.0)`) +- Complex expressions, computed properties, or method calls are not supported + +## Unsupported Default Value Types + +The following expressions are **not supported** as default parameter values: + +| Expression Type | Example | Status | +|:----------------|:--------|:-------| +| Method calls | `Date().description` | ❌ | +| Closures | `{ "computed" }()` | ❌ | +| Dictionary literals | `["key": "value"]` | ❌ | +| Binary operations | `10 + 20` | ❌ | +| Complex member access | `Config.shared.value` | ❌ | +| Ternary operators | `flag ? "a" : "b"` | ❌ | +| Object init with complex args | `Config(setting: getValue())` | ❌ | diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Enum.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Enum.md new file mode 100644 index 000000000..2220d457c --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Enum.md @@ -0,0 +1,517 @@ +# Exporting Swift Enums to JS + +Learn how to export Swift enums to JavaScript. + +## Overview + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +BridgeJS supports two output styles for enums, controlled by the `enumStyle` parameter: + +- **`.const` (default)**: Generates const objects with union types +- **`.tsEnum`**: Generates native TypeScript enum declarations - **only available for case enums and raw value enums with String or numeric raw types** + +Examples output of both styles can be found below. + +BridgeJS generates separate objects with descriptive naming for `.const` enums: + +- **`EnumNameValues`**: Contains the enum case constants for all enums +- **`EnumNameTag`**: Represents the union type for enums +- **`EnumNameObject`**: Object type for all const-style enums, contains static members for enums with methods/properties or references the values type for simple enums + +### Case Enums + +```swift +@JS enum Direction { + case north + case south + case east + case west +} + +@JS(enumStyle: .tsEnum) enum TSDirection { + case north + case south + case east + case west +} + +@JS enum Status { + case loading + case success + case error +} +``` + +Generated TypeScript declarations: + +```typescript +// Const object style (default) +export const DirectionValues: { + readonly North: 0; + readonly South: 1; + readonly East: 2; + readonly West: 3; +}; +export type DirectionTag = typeof DirectionValues[keyof typeof DirectionValues]; + +// Native TypeScript enum style +export enum TSDirection { + North = 0, + South = 1, + East = 2, + West = 3, +} + +export const StatusValues: { + readonly Loading: 0; + readonly Success: 1; + readonly Error: 2; +}; +export type StatusTag = typeof StatusValues[keyof typeof StatusValues]; +``` + +In TypeScript: + +```typescript +const direction: DirectionTag = DirectionValues.North; +const tsDirection: TSDirection = TSDirection.North; +const status: StatusTag = StatusValues.Loading; + +exports.setDirection(DirectionValues.South); +exports.setTSDirection(TSDirection.East); +const currentDirection: DirectionTag = exports.getDirection(); +const currentTSDirection: TSDirection = exports.getTSDirection(); + +const result: StatusTag = exports.processDirection(DirectionValues.East); + +function handleDirection(direction: DirectionTag) { + switch (direction) { + case DirectionValues.North: + console.log("Going north"); + break; + case DirectionValues.South: + console.log("Going south"); + break; + // TypeScript will warn about missing cases + } +} +``` + +### Raw Value Enums + +#### String Raw Values + +```swift +// Default const object style +@JS enum Theme: String { + case light = "light" + case dark = "dark" + case auto = "auto" +} + +// Native TypeScript enum style +@JS(enumStyle: .tsEnum) enum TSTheme: String { + case light = "light" + case dark = "dark" + case auto = "auto" +} +``` + +Generated TypeScript declarations: + +```typescript +// Const object style (default) +export const ThemeValues: { + readonly Light: "light"; + readonly Dark: "dark"; + readonly Auto: "auto"; +}; +export type ThemeTag = typeof ThemeValues[keyof typeof ThemeValues]; + +// Native TypeScript enum style +export enum TSTheme { + Light = "light", + Dark = "dark", + Auto = "auto", +} +``` + +In TypeScript: + +```typescript +// Raw value enums work similarly to case enums +const theme: ThemeTag = ThemeValues.Dark; +const tsTheme: TSTheme = TSTheme.Dark; + +exports.setTheme(ThemeValues.Light); +const currentTheme: ThemeTag = exports.getTheme(); + +const status: HttpStatusTag = exports.processTheme(ThemeValues.Auto); +``` + +#### Integer Raw Values + +```swift +// Default const object style +@JS enum HttpStatus: Int { + case ok = 200 + case notFound = 404 + case serverError = 500 +} + +// Native TypeScript enum style +@JS(enumStyle: .tsEnum) enum TSHttpStatus: Int { + case ok = 200 + case notFound = 404 + case serverError = 500 +} + +@JS enum Priority: Int32 { + case lowest = 1 + case low = 2 + case medium = 3 + case high = 4 + case highest = 5 +} +``` + +Generated TypeScript declarations: + +```typescript +// Const object style (default) +export const HttpStatusValues: { + readonly Ok: 200; + readonly NotFound: 404; + readonly ServerError: 500; +}; +export type HttpStatusTag = typeof HttpStatusValues[keyof typeof HttpStatusValues]; + +// Native TypeScript enum style +export enum TSHttpStatus { + Ok = 200, + NotFound = 404, + ServerError = 500, +} + +export const PriorityValues: { + readonly Lowest: 1; + readonly Low: 2; + readonly Medium: 3; + readonly High: 4; + readonly Highest: 5; +}; +export type PriorityTag = typeof PriorityValues[keyof typeof PriorityValues]; +``` + +In TypeScript: + +```typescript +const status: HttpStatusTag = HttpStatusValues.Ok; +const tsStatus: TSHttpStatus = TSHttpStatus.Ok; +const priority: PriorityTag = PriorityValues.High; + +exports.setHttpStatus(HttpStatusValues.NotFound); +exports.setPriority(PriorityValues.Medium); + +const convertedPriority: PriorityTag = exports.convertPriority(HttpStatusValues.Ok); +``` + +### Namespace Enums + +Namespace enums are empty enums (containing no cases) used for organizing related types and functions into hierarchical namespaces. See for more details on namespace organization. + +```swift +@JS enum Utils { + @JS class Converter { + @JS init() {} + + @JS func toString(value: Int) -> String { + return String(value) + } + } +} + +// Nested namespace enums with no @JS(namespace:) macro used +@JS enum Networking { + @JS enum API { + @JS enum Method { + case get + case post + } + + @JS class HTTPServer { + @JS init() {} + @JS func call(_ method: Method) + } + } +} + +// Top level enum can still use explicit namespace via @JS(namespace:) +@JS(namespace: "Networking.APIV2") +enum Internal { + @JS enum SupportedMethod { + case get + case post + } + + @JS class TestServer { + @JS init() {} + @JS func call(_ method: SupportedMethod) + } +} +``` + +Generated TypeScript declarations: + +```typescript +declare global { + namespace Utils { + class Converter { + constructor(); + toString(value: number): string; + } + } + namespace Networking { + namespace API { + class HTTPServer { + constructor(); + call(method: Networking.API.MethodTag): void; + } + const MethodValues: { + readonly Get: 0; + readonly Post: 1; + }; + type MethodTag = typeof MethodValues[keyof typeof MethodValues]; + } + namespace APIV2 { + namespace Internal { + class TestServer { + constructor(); + call(method: Internal.SupportedMethodTag): void; + } + const SupportedMethodValues: { + readonly Get: 0; + readonly Post: 1; + }; + type SupportedMethodTag = typeof SupportedMethodValues[keyof typeof SupportedMethodValues]; + } + } + } +} +``` + +In TypeScript: + +```typescript +// Access nested classes through namespaces (no globalThis prefix needed) +const converter = new Utils.Converter(); +const result: string = converter.toString(42) + +const server = new Networking.API.HTTPServer(); +const method: Networking.API.MethodTag = Networking.API.MethodValues.Get; +server.call(method) + +const testServer = new Networking.APIV2.Internal.TestServer(); +const supportedMethod: Internal.SupportedMethodTag = Networking.APIV2.Internal.SupportedMethodValues.Post; +testServer.call(supportedMethod); +``` + +Things to remember when using enums for namespacing: + +1. Only enums with no cases will be used for namespaces +2. Top-level enums can use `@JS(namespace: "Custom.Path")` to place themselves in custom namespaces, which will be used as "base namespace" for all nested elements as well +3. Classes and enums nested within namespace enums **cannot** use `@JS(namespace:)` - this would create conflicting namespace declarations + +Invalid usage: + +```swift +@JS enum Utils { + // Invalid - nested items cannot specify their own namespace + @JS(namespace: "Custom") class Helper { + @JS init() {} + } +} +``` + +Valid usage: + +```swift +// Valid - top-level enum with explicit namespace +@JS(namespace: "Custom.Utils") +enum Helper { + @JS class Converter { + @JS init() {} + } +} +``` + +### Associated Value Enums + +Associated value enums are supported and allow you to pass data along with each enum case. BridgeJS generates TypeScript discriminated union types. Associated values are encoded into a binary format for efficient transfer between JavaScript and WebAssembly + +```swift +@JS +enum APIResult { + case success(String) + case failure(Int) + case flag(Bool) + case rate(Float) + case precise(Double) + case info +} + +@JS +enum ComplexResult { + case success(String) + case error(String, Int) + case status(Bool, Int, String) + case coordinates(Double, Double, Double) + case comprehensive(Bool, Bool, Int, Int, Double, Double, String, String, String) + case info +} + +@JS func handle(result: APIResult) +@JS func getResult() -> APIResult +``` + +Generated TypeScript declarations: + +```typescript +export const APIResultValues: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + readonly Flag: 2; + readonly Rate: 3; + readonly Precise: 4; + readonly Info: 5; + }; +}; + +export type APIResultTag = + { tag: typeof APIResultValues.Tag.Success; param0: string } | + { tag: typeof APIResultValues.Tag.Failure; param0: number } | + { tag: typeof APIResultValues.Tag.Flag; param0: boolean } | + { tag: typeof APIResultValues.Tag.Rate; param0: number } | + { tag: typeof APIResultValues.Tag.Precise; param0: number } | + { tag: typeof APIResultValues.Tag.Info } + +export const ComplexResultValues: { + readonly Tag: { + readonly Success: 0; + readonly Error: 1; + readonly Status: 2; + readonly Coordinates: 3; + readonly Comprehensive: 4; + readonly Info: 5; + }; +}; + +export type ComplexResultTag = + { tag: typeof ComplexResultValues.Tag.Success; param0: string } | + { tag: typeof ComplexResultValues.Tag.Error; param0: string; param1: number } | + { tag: typeof ComplexResultValues.Tag.Status; param0: boolean; param1: number; param2: string } | + { tag: typeof ComplexResultValues.Tag.Coordinates; param0: number; param1: number; param2: number } | + { tag: typeof ComplexResultValues.Tag.Comprehensive; param0: boolean; param1: boolean; param2: number; param3: number; param4: number; param5: number; param6: string; param7: string; param8: string } | + { tag: typeof ComplexResultValues.Tag.Info } +``` + +In TypeScript: + +```typescript +const successResult: APIResultTag = { + tag: APIResultValues.Tag.Success, + param0: "Operation completed successfully" +}; + +const errorResult: ComplexResultTag = { + tag: ComplexResultValues.Tag.Error, + param0: "Network timeout", + param1: 503 +}; + +const statusResult: ComplexResultTag = { + tag: ComplexResultValues.Tag.Status, + param0: true, + param1: 200, + param2: "OK" +}; + +exports.handle(successResult); +exports.handle(errorResult); + +const result: APIResultTag = exports.getResult(); + +// Pattern matching with discriminated unions +function processResult(result: APIResultTag) { + switch (result.tag) { + case APIResultValues.Tag.Success: + console.log("Success:", result.param0); // TypeScript knows param0 is string + break; + case APIResultValues.Tag.Failure: + console.log("Failure code:", result.param0); // TypeScript knows param0 is number + break; + case APIResultValues.Tag.Flag: + console.log("Flag value:", result.param0); // TypeScript knows param0 is boolean + break; + case APIResultValues.Tag.Info: + console.log("Info case has no associated data"); + break; + // TypeScript will warn about missing cases + } +} +``` + +## How It Works + +Enums use **copy semantics** when crossing the Swift/JavaScript boundary: + +1. **Case Enums**: Passed as integer tag values (0, 1, 2, ...) representing each case +2. **Raw Value Enums**: Passed using their raw value type (string or integer) +3. **Associated Value Enums**: Tag value passed directly, associated data pushed to type-specific stacks and reconstructed on the receiving side + +BridgeJS generates convenience initializers and computed properties for each enum, keeping the glue code minimal and consistent: + +```swift +extension Direction { + init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: self = .north + case 1: self = .south + // ... + default: return nil + } + } + + var bridgeJSRawValue: Int32 { + switch self { + case .north: return 0 + case .south: return 1 + // ... + } + } +} +``` + +This differs from classes, which use reference semantics and share state across the boundary. + +## Supported Features + +| Swift Feature | Status | +|:--------------|:-------| +| Case enums | ✅ | +| Raw value enums (`String`) | ✅ | +| Raw value enums (`Int`, `Int32`, etc.) | ✅ | +| Namespace enums (empty enums) | ✅ | +| Associated value enums | ✅ | +| `.tsEnum` style option | ✅ | +| Static functions | ✅ | +| Static properties | ✅ | +| Associated values: `String`, `Int`, `Bool`, `Float`, `Double` | ✅ | +| Associated values: Custom classes/structs | ✅ | +| Associated values: Other enums (case, raw value, and associated value) | ✅ | +| Associated values: `JSObject` | ✅ | +| Associated values: Arrays | ✅ | +| Associated values: Optionals of all supported types | ✅ | +| Generics | ❌ | diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Function.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Function.md new file mode 100644 index 000000000..c26841041 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Function.md @@ -0,0 +1,153 @@ +# Exporting Swift Functions to JS + +Learn how to export Swift functions to JavaScript. + +## Overview + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +To export a Swift function to JavaScript, mark it with the `@JS` attribute and make it `public`: + +```swift +import JavaScriptKit + +@JS public func calculateTotal(price: Double, quantity: Int) -> Double { + return price * Double(quantity) +} + +@JS public func formatCurrency(amount: Double) -> String { + return "$\(String(format: "%.2f", amount))" +} +``` + +These functions will be accessible from JavaScript: + +```javascript +const total = exports.calculateTotal(19.99, 3); +const formattedTotal = exports.formatCurrency(total); +console.log(formattedTotal); // "$59.97" +``` + +The generated TypeScript declarations for these functions would look like: + +```typescript +export type Exports = { + calculateTotal(price: number, quantity: number): number; + formatCurrency(amount: number): string; +} +``` + +### Throwing functions + +Swift functions can throw JavaScript errors using `throws(JSException)`. + +```swift +import JavaScriptKit + +@JS public func findUser(id: Int) throws(JSException) -> String { + if id <= 0 { + throw JSException(JSError(message: "Invalid ID").jsValue) + } + return "User_\(id)" +} +``` + +From JavaScript, call with `try/catch`: + +```javascript +try { + const name = exports.findUser(42); + console.log(name); +} catch (e) { + console.error("findUser failed:", e); +} +``` + +Generated TypeScript type: + +```typescript +export type Exports = { + findUser(id: number): string; // throws at runtime +} +``` + +Notes: +- Only `throws(JSException)` is supported. Plain `throws` is not supported. +- Thrown values are surfaced to JS as normal JS exceptions. + +### Async functions + +Async Swift functions are exposed as Promise-returning JS functions. + +```swift +import JavaScriptKit + +@JS public func fetchCount(endpoint: String) async -> Int { + // Simulate async work + try? await Task.sleep(nanoseconds: 50_000_000) + return endpoint.count +} +``` + +Usage from JavaScript: + +```javascript +const count = await exports.fetchCount("/items"); +``` + +Generated TypeScript type: + +```typescript +export type Exports = { + fetchCount(endpoint: string): Promise; +} +``` + +### Async + throws + +Async throwing functions become Promise-returning JS functions that reject on error. + +```swift +import JavaScriptKit + +@JS public func loadProfile(userId: Int) async throws(JSException) -> String { + if userId <= 0 { throw JSException(JSError(message: "Bad userId").jsValue) } + try? await Task.sleep(nanoseconds: 50_000_000) + return "Profile_\(userId)" +} +``` + +JavaScript usage: + +```javascript +try { + const profile = await exports.loadProfile(1); + console.log(profile); +} catch (e) { + console.error("loadProfile failed:", e); +} +``` + +TypeScript: + +```typescript +export type Exports = { + loadProfile(userId: number): Promise; +} +``` + +## Supported Features + +| Swift Feature | Status | +|:--------------|:-------| +| Primitive parameter/result types: (e.g. `Bool`, `Int`, `Double`) | ✅ | +| `String` parameter/result type | ✅ | +| `@JS class` parameter/result type | ✅ | +| `@JS enum` parameter/result type | ✅ | +| `JSObject` parameter/result type | ✅ | +| Throwing JS exception: `func x() throws(JSException)` | ✅ | +| Throwing any exception: `func x() throws` | ❌ | +| Async methods: `func x() async` | ✅ | +| Generics | ❌ | +| Opaque types: `func x() -> some P`, `func y(_: some P)` | ❌ | +| Default parameter values: `func x(_ foo: String = "")` | ✅ (See ) | \ No newline at end of file diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Optional.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Optional.md new file mode 100644 index 000000000..be15b762f --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Optional.md @@ -0,0 +1,125 @@ +# Exporting Swift Optionals to JS + +Learn how to use Swift optionals in functions, classes, and enums exported to JavaScript. + +## Overview + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +BridgeJS provides comprehensive support for Swift optionals across all bridged types. When you use `Optional` or `T?` in Swift, it automatically maps to `T | null` in TypeScript/JavaScript. + +Swift optionals are translated to union types with `null` (not `undefined`) because `null` represents an explicit "no value" state that aligns semantically with Swift's `nil`. This design choice ensures consistent null handling across the Swift-JavaScript bridge and avoids the ambiguity that comes with JavaScript's `undefined`. + +## Supported Optional Syntax + +BridgeJS recognizes all Swift optional syntax variants: + +```swift +// All of these work identically +@JS func test(name: String?) -> String? { return name } +@JS func test(name: Optional) -> Optional { return name } +@JS func test(name: Swift.Optional) -> Swift.Optional { return name } +@JS func test(name: Swift.Optional< String >) -> Swift.Optional< String. > { return name } + +// Type aliases work too +typealias OptionalName = String? +@JS func test(name: OptionalName) -> OptionalName { return name } +``` + +## Optional Parameters + +All parameter types can be made optional, including primitives, objects, and enums: + +```swift +@JS public func processOptionalData( + text: String?, // Optional string + count: Int?, // Optional integer + flag: Bool?, // Optional boolean + rate: Double?, // Optional double + user: User? // Optional Swift class +) -> String +``` + +Generated TypeScript type: + +```typescript +export type Exports = { + processOptionalData( + text: string | null, + count: number | null, + flag: boolean | null, + rate: number | null, + user: User | null + ): string; +} +``` + +## Optional Return Values + +Functions can return optional values of any supported type: + +```swift +@JS public func processText(input: String?) -> String? +``` + +Generated TypeScript type: + +```typescript +export type Exports = { + processText( + input: string | null + ): string | null; +} +``` + +## Optionals in classes + +Class properties can be optional with proper getter/setter support. +Constructors can accept optional parameters. + +```swift +@JS public class UserProfile { + @JS public var name: String? + @JS public var email: String? + @JS public var age: Int? + @JS public var avatar: User? + + @JS public init(name: String?) + @JS public func updateProfile(email: String?, age: Int?) +} + +``` + +Generated TypeScript definition: + +```typescript +export interface UserProfile extends SwiftHeapObject { + name: string | null; + email: string | null; + age: number | null; + avatar: User | null; + + updateProfile(email: string | null, age: number | null): void; +} +export type UserProfile = { + UserProfile: { + new(name: string | null): UserProfile; + } +} +``` + +## Supported Features + +| Swift Feature | Status | +|:--------------|:-------| +| Optional primitive parameters: `Int?`, `String?`, etc. | ✅ | +| Optional primitive return values | ✅ | +| Optional object parameters: `MyClass?`, `JSObject?` | ✅ | +| Optional object return values | ✅ | +| Optional enum type parameters and returns | ✅ | +| Optional properties within associated value enum cases | ✅ | +| Optional properties in classes | ✅ | +| Optional constructor parameters | ✅ | +| Type aliases for optionals | ✅ | +| All optional syntax: `T?`, `Optional`, `Swift.Optional` | ✅ | +| Nested optionals: `T??` | ❌ | \ No newline at end of file diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Protocols.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Protocols.md new file mode 100644 index 000000000..3b2ec1526 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Protocols.md @@ -0,0 +1,225 @@ +# Exporting Swift Protocols to JS + +Learn how to expose Swift protocols to JavaScript as TypeScript interfaces. + +## Overview + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +BridgeJS allows you to export Swift protocols as TypeScript interfaces. JavaScript objects implementing these interfaces can be passed to Swift code, enabling protocol-oriented design across the Swift-JavaScript boundary. + +When you mark a protocol with `@JS`, BridgeJS generates: + +- A TypeScript interface with the protocol's method signatures +- A Swift wrapper struct (`Any{ProtocolName}`) that conforms to the protocol and bridges calls to JavaScript objects + +## Example: Counter Protocol + +Mark a Swift protocol with `@JS` to expose it: + +```swift +import JavaScriptKit + +@JS protocol Counter { + var count: Int { get set } + var name: String { get } + var label: String? { get set } + func increment(by amount: Int) + func reset() + func getValue() -> Int +} + +@JS class CounterManager { + var delegate: Counter + + @JS init(delegate: Counter) { + self.delegate = delegate + } + + @JS func incrementTwice() { + delegate.increment(by: 1) + delegate.increment(by: 1) + } + + @JS func getCurrentValue() -> Int { + return delegate.getValue() + } + + @JS func getCounterName() -> String { + return delegate.name + } + + @JS func setCountValue(_ value: Int) { + delegate.count = value + } + + @JS func updateLabel(_ newLabel: String?) { + delegate.label = newLabel + } +} +``` + +In JavaScript: + +```javascript +import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; +const { exports } = await init({}); + +// Implement the Counter protocol +const counterImpl = { + count: 0, + name: "JSCounter", + label: "Default Label", + increment(amount) { + this.count += amount; + }, + reset() { + this.count = 0; + }, + getValue() { + return this.count; + } +}; + +// Pass the implementation to Swift +const manager = new exports.CounterManager(counterImpl); +manager.incrementTwice(); +console.log(manager.getCurrentValue()); // 2 +console.log(manager.getCounterName()); // "JSCounter" +manager.setCountValue(10); +console.log(counterImpl.count); // 10 + +manager.updateLabel("Custom Label"); +console.log(counterImpl.label); // "Custom Label" +manager.updateLabel(null); +console.log(counterImpl.label); // null +``` + +The generated TypeScript interface: + +```typescript +export interface Counter { + count: number; + readonly name: string; + label: string | null; + increment(amount: number): void; + reset(): void; + getValue(): number; +} + +export type Exports = { + CounterManager: { + new(delegate: Counter): CounterManager; + } +} +``` + +## Swift Implementation + +You can also implement protocols in Swift and use them from JavaScript: + +```swift +@JS protocol Counter { + var count: Int { get set } + var name: String { get } + func increment(by amount: Int) + func reset() + func getValue() -> Int +} + +final class SwiftCounter: Counter { + var count = 0 + let name = "SwiftCounter" + + func increment(by amount: Int) { + count += amount + } + + func reset() { + count = 0 + } + + func getValue() -> Int { + return count + } +} + +@JS func createCounter() -> Counter { + return SwiftCounter() +} +``` + +From JavaScript: + +```javascript +const counter = exports.createCounter(); +console.log(counter.name); // "SwiftCounter" +counter.increment(5); +counter.increment(3); +console.log(counter.getValue()); // 8 +console.log(counter.count); // 8 +counter.count = 100; +console.log(counter.getValue()); // 100 +counter.reset(); +console.log(counter.getValue()); // 0 +``` + +## How It Works + +Protocols use **reference semantics** when crossing the Swift/JavaScript boundary: + +1. **JavaScript → Swift**: The JavaScript object is stored in JavaScriptKit's memory heap and its ID is passed as an `Int32` to Swift +2. **Wrapper Generation**: BridgeJS generates an `Any{ProtocolName}` wrapper struct that holds a `JSObject` reference and forwards protocol method calls through WASM to the JavaScript implementation +3. **Swift → JavaScript**: When returning a Swift protocol implementation to JavaScript, the object is stored on the Swift heap and JavaScript receives a reference +4. **Memory Management**: `FinalizationRegistry` automatically handles cleanup. The `JSObject` reference keeps the JavaScript object alive, and when the Swift wrapper is deallocated, the JavaScript object is released. + +### Generated Wrapper + +BridgeJS generates a Swift wrapper struct for each `@JS` protocol: + +```swift +struct AnyCounter: Counter, _BridgedSwiftProtocolWrapper { + let jsObject: JSObject + + var count: Int { + get { + @_extern(wasm, module: "TestModule", name: "bjs_Counter_count_get") + func _extern_get(this: Int32) -> Int32 + let ret = _extern_get(this: Int32(bitPattern: jsObject.id)) + return Int.bridgeJSLiftReturn(ret) + } + set { + @_extern(wasm, module: "TestModule", name: "bjs_Counter_count_set") + func _extern_set(this: Int32, value: Int32) + _extern_set(this: Int32(bitPattern: jsObject.id), value: newValue.bridgeJSLowerParameter()) + } + } + + func increment(by amount: Int) { + @_extern(wasm, module: "TestModule", name: "bjs_Counter_increment") + func _extern_increment(this: Int32, amount: Int32) + _extern_increment( + this: Int32(bitPattern: jsObject.id), + amount: amount.bridgeJSLowerParameter() + ) + } + + // ... other protocol requirements +} +``` + +## Supported Features + +| Swift Feature | Status | +|:--------------|:-------| +| Method requirements: `func foo(_ param: String?) -> FooClass?` | ✅ | +| Property requirements: `var property: Type { get }` / `var property: Type { get set }` | ✅ | +| Optional parameters / return values in methods | ✅ | +| Optional properties | ✅ | +| Optional protocol methods | ❌ | +| Associated types | ❌ | +| Protocol inheritance | ❌ | +| Protocol composition: `Protocol1 & Protocol2` | ❌ | +| Generics | ❌ | + +> Note: Protocol type support matches that of regular `@JS func` and `@JS class` exports. See , , and for more information. diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Functions.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Functions.md new file mode 100644 index 000000000..1c4b22abe --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Functions.md @@ -0,0 +1,166 @@ +# Exporting Swift Static Functions to JS + +Learn how to export Swift static and class functions as JavaScript static methods using BridgeJS. + +## Overview + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +BridgeJS supports exporting Swift `static func` and `class func` to JavaScript static methods. Both generate identical JavaScript output but differ in Swift inheritance behavior. + +> Important: Static function support is **Swift → JavaScript only**. JavaScript → Swift static function imports are not currently supported. + +## Class Static Functions + +Classes can export both `static` and `class` functions: + +```swift +@JS class MathUtils { + @JS init() {} + + @JS static func add(a: Int, b: Int) -> Int { + return a + b + } + + @JS class func subtract(a: Int, b: Int) -> Int { + return a - b + } + + @JS func multiply(x: Int, y: Int) -> Int { + return x * y + } +} +``` + +Generated TypeScript definitions: + +```typescript +export type Exports = { + MathUtils: { + new(): MathUtils; + subtract(a: number, b: number): number; + add(a: number, b: number): number; + } +} + +export interface MathUtils extends SwiftHeapObject { + multiply(x: number, y: number): number; +} +``` + +Usage: + +```typescript +// Static methods +const sum = MathUtils.add(5, 3); +const difference = MathUtils.subtract(10, 4); + +// Instance methods +const utils = new MathUtils(); +const product = utils.multiply(4, 7); +``` + +## Values/Tag/Object Pattern + +For enums with static functions, BridgeJS generates a structured pattern: + +- **Values**: Constants for enum cases (`CalculatorValues: { readonly Scientific: 0; readonly Basic: 1; }`) +- **Tag**: Type alias for enum values (`CalculatorTag = typeof CalculatorValues[keyof typeof CalculatorValues]`) +- **Object**: Intersection type combining Values + methods (`CalculatorObject = typeof CalculatorValues & { methods }`) +- **Exports**: Uses Object type for unified access (`Calculator: CalculatorObject`) + +This allows accessing both enum constants and static functions through a single interface: `exports.Calculator.Scientific` and `exports.Calculator.square(5)`. + +## Enum Static Functions + +Enums can contain static functions that are exported as properties: + +```swift +@JS enum Calculator { + case scientific + case basic + + @JS static func square(value: Int) -> Int { + return value * value + } + + @JS static func cube(value: Int) -> Int { + return value * value * value + } +} +``` + +Generated TypeScript definitions: + +```typescript +export const CalculatorValues: { + readonly Scientific: 0; + readonly Basic: 1; +}; +export type CalculatorTag = typeof CalculatorValues[keyof typeof CalculatorValues]; + +export type CalculatorObject = typeof CalculatorValues & { + square(value: number): number; + cube(value: number): number; +}; + +export type Exports = { + Calculator: CalculatorObject +} +``` + +This enables unified access to both enum constants and static functions: + +```typescript +// Access enum constants +const mode: CalculatorTag = exports.Calculator.Scientific; // 0 +const otherMode: CalculatorTag = CalculatorValues.Basic; // 1 + +// Call static functions +const result: number = exports.Calculator.square(5); // 25 +``` + +## Namespace Enum Static Functions + +Namespace enums organize related utility functions and are assigned to `globalThis`. See for more details on namespace organization. + +```swift +@JS enum Utils { + @JS enum String { + @JS static func uppercase(_ text: String) -> String { + return text.uppercased() + } + } +} +``` + +Generated TypeScript definitions: + +```typescript +declare global { + namespace Utils { + namespace String { + function uppercase(text: string): string; + } + } +} +``` + +Usage: + +```typescript +// Direct access via global namespace (no exports needed) +const upper: string = Utils.String.uppercase("hello"); +const result: string = Utils.String.uppercase("world"); +``` + +## Supported Features + +| Swift Feature | Status | +|:--------------|:-------| +| Class `static func` | ✅ | +| Class `class func` | ✅ | +| Enum `static func` | ✅ | +| Namespace enum `static func` | ✅ | +| Generic static functions | ❌ | +| Protocol static requirements | ❌ | diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Properties.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Properties.md new file mode 100644 index 000000000..4898535c8 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Properties.md @@ -0,0 +1,188 @@ +# Exporting Swift Static Properties to JS + +Learn how to export Swift static and class properties as JavaScript static properties using BridgeJS. + +## Overview + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +BridgeJS supports exporting Swift `static var`, `static let`, and `class var` properties to JavaScript static properties. Both stored and computed properties are supported. + +## Class Static Properties + +Classes can export both stored and computed static properties: + +```swift +@JS class Configuration { + @JS init() {} + + @JS static let version = "1.0.0" + @JS static var debugMode = false + @JS class var defaultTimeout = 30 + + @JS static var timestamp: Double { + get { return Date().timeIntervalSince1970 } + set { /* custom setter logic */ } + } + + @JS static var buildNumber: Int { + return 12345 + } +} +``` + +Generated TypeScript definitions: + +```typescript +export type Exports = { + Configuration: { + new(): Configuration; + readonly version: string; + debugMode: boolean; + defaultTimeout: number; + timestamp: number; + readonly buildNumber: number; + } +} + +export interface Configuration extends SwiftHeapObject { + // instance methods here +} +``` + +Usage: + +```typescript +console.log(Configuration.version); // "1.0.0" +console.log(Configuration.debugMode); // false +console.log(Configuration.timestamp); // current timestamp + +Configuration.debugMode = true; +Configuration.timestamp = Date.now() / 1000; +``` + + +## Values/Tag/Object Pattern + +For enums with static properties, BridgeJS generates a structured pattern: + +- **Values**: Constants for enum cases (`PropertyEnumValues: { readonly Value1: 0; readonly Value2: 1; }`) +- **Tag**: Type alias for enum values (`PropertyEnumTag = typeof PropertyEnumValues[keyof typeof PropertyEnumValues]`) +- **Object**: Intersection type combining Values + properties (`PropertyEnumObject = typeof PropertyEnumValues & { properties }`) +- **Exports**: Uses Object type for unified access (`PropertyEnum: PropertyEnumObject`) + +This allows accessing both enum constants and static properties through a single interface: `exports.PropertyEnum.Value1` and `exports.PropertyEnum.enumProperty`. + +## Enum Static Properties + +Enums can contain static properties that are exported alongside enum cases: + +```swift +@JS enum PropertyEnum { + case value1 + case value2 + + @JS static var enumProperty = "mutable" + @JS static let enumConstant = 42 + @JS static var computedEnum: String { + return "computed value" + } +} +``` + +Generated TypeScript definitions: + +```typescript +export const PropertyEnumValues: { + readonly Value1: 0; + readonly Value2: 1; +}; +export type PropertyEnumTag = typeof PropertyEnumValues[keyof typeof PropertyEnumValues]; + +export type PropertyEnumObject = typeof PropertyEnumValues & { + enumProperty: string; + readonly enumConstant: number; + computedEnum: string; +}; + +export type Exports = { + PropertyEnum: PropertyEnumObject +} +``` + +Usage: + +```typescript +const status: PropertyEnumTag = exports.PropertyEnum.Value1; // 0 +const otherStatus: PropertyEnumTag = PropertyEnumValues.Value2; // 1 + +// Access static properties +console.log(exports.PropertyEnum.enumProperty); // "mutable" +console.log(exports.PropertyEnum.enumConstant); // 42 +console.log(exports.PropertyEnum.computedEnum); // "computed value" + +// Modify mutable properties +exports.PropertyEnum.enumProperty = "updated"; + +``` + +## Namespace Enum Static Properties + +Namespace enums organize related static properties and are assigned to `globalThis`. See for more details on namespace organization. + +```swift +@JS enum PropertyNamespace { + @JS enum Nested { + @JS static var nestedConstant = "constant" + @JS static var nestedDouble = 3.14 + @JS static var nestedProperty = 100 + } +} +``` + +Generated TypeScript definitions: + +```typescript +declare global { + namespace PropertyNamespace { + namespace Nested { + var nestedConstant: string; + let nestedDouble: number; + let nestedProperty: number; + } + } +} +``` + +JavaScript usage: + +```typescript +// Direct access via global namespace (no exports needed) +console.log(PropertyNamespace.Nested.nestedConstant); // "constant" +console.log(PropertyNamespace.Nested.nestedDouble); // 3.14 +console.log(PropertyNamespace.Nested.nestedProperty); // 100 + +// Modify mutable properties +PropertyNamespace.Nested.nestedConstant = "updated"; +PropertyNamespace.Nested.nestedProperty = 200; + +// Type-safe access +const constant: string = PropertyNamespace.Nested.nestedConstant; +const value: number = PropertyNamespace.Nested.nestedProperty; +``` + +## Supported Features + +| Swift Feature | Status | +|:--------------|:-------| +| Class `static let` | ✅ | +| Class `static var` | ✅ | +| Class `class var` | ✅ | +| Enum static properties | ✅ | +| Namespace enum static properties | ✅ | +| Computed properties (get/set) | ✅ | +| Read-only computed properties | ✅ | +| All property types (primitives, objects, optionals) | ✅ | +| Property observers (`willSet`/`didSet`) | ❌ | +| Generic static properties | ❌ | +| Protocol static property requirements | ❌ | diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Struct.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Struct.md new file mode 100644 index 000000000..32bb79ed3 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Struct.md @@ -0,0 +1,174 @@ +# Exporting Swift Structs to JS + +Learn how to export Swift structs to JavaScript. + +## Overview + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +To export a Swift struct, mark it with `@JS`: + +```swift +import JavaScriptKit + +@JS struct Point { + var x: Double + var y: Double + var label: String +} + +@JS struct Address { + var street: String + var city: String + var zipCode: Int? +} + +@JS struct Person { + var name: String + var age: Int + var address: Address + var email: String? +} + +@JS func createPerson(name: String, age: Int, street: String, city: String) -> Person +@JS func updateEmail(person: Person, email: String?) -> Person +``` + +In JavaScript: + +```javascript +import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; +const { exports } = await init({}); + +const person = exports.createPerson("Alice", 30, "123 Main St", "NYC"); +console.log(person.name); // "Alice" +console.log(person.address.street); // "123 Main St" +console.log(person.email); // null + +const updated = exports.updateEmail(person, "alice@example.com"); +console.log(updated.email); // "alice@example.com" +``` + +The generated TypeScript declarations: + +```typescript +export interface Point { + x: number; + y: number; + label: string; +} + +export interface Address { + street: string; + city: string; + zipCode: number | null; +} + +export interface Person { + name: string; + age: number; + address: Address; + email: string | null; +} + +export type Exports = { + createPerson(name: string, age: number, street: string, city: string): Person; + updateEmail(person: Person, email: string | null): Person; +} +``` + +## Instance Fields vs Static Properties + +**Instance fields** (part of the struct value) are automatically exported - no `@JS` needed: +```swift +@JS struct Point { + var x: Double // Auto-exported + var y: Double // Auto-exported +} +``` + +**Static properties** (not part of instance) require `@JS`: +```swift +@JS struct Config { + var name: String + + @JS nonisolated(unsafe) static var defaultTimeout: Double = 30.0 + @JS static let maxRetries: Int = 3 +} +``` + +In JavaScript: +```javascript +console.log(exports.Config.defaultTimeout); // 30.0 +exports.Config.defaultTimeout = 60.0; +console.log(exports.Config.maxRetries); // 3 (readonly) +``` + +## Struct Methods and Initializers + +Structs can have instance methods, static methods, and initializers. All require `@JS` annotation: + +```swift +@JS struct Point { + var x: Double + var y: Double + + @JS init(x: Double, y: Double) { + self.x = x + self.y = y + } + + @JS func distanceFromOrigin() -> Double { + return (x * x + y * y).squareRoot() + } + + @JS static func origin() -> Point { + return Point(x: 0, y: 0) + } +} +``` + +In JavaScript: + +```javascript +// Create via static init method (not constructor) +const point = exports.Point.init(3.0, 4.0); +console.log(point.distanceFromOrigin()); // 5.0 + +// Static method +const origin = exports.Point.origin(); +console.log(origin.x); // 0.0 +``` + +Note: Struct initializers are exported as static `init` methods. This differs from classes, where `@JS init` maps to a JavaScript constructor using `new`. + +## How It Works + +Structs use **copy semantics** when crossing the Swift/JavaScript boundary: + +1. **Data Transfer**: Struct fields are pushed to type-specific stacks and reconstructed as plain JavaScript objects +2. **No Shared State**: Each side has its own copy - modifications don't affect the other +3. **No Memory Management**: No `release()` needed since there's no shared reference +4. **Plain Objects**: In JavaScript, structs become plain objects matching the TypeScript interface + +This differs from classes, which use reference semantics and share state across the boundary. + +## Supported Features + +| Swift Feature | Status | +|:--------------|:-------| +| Stored fields with supported types | ✅ | +| Optional fields | ✅ | +| Nested structs | ✅ | +| `JSObject` fields | ✅ | +| `@JSClass struct` fields | ✅ | +| Instance methods | ✅ | +| Static methods | ✅ | +| Static properties | ✅ | +| Property observers (`willSet`, `didSet`) | ❌ | +| Generics | ❌ | +| Conformances | ❌ | + +## See Also + +- diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Using-Namespace.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Using-Namespace.md new file mode 100644 index 000000000..1aff82f65 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Using-Namespace.md @@ -0,0 +1,123 @@ +# Using Namespaces + +Learn how to organize exported Swift code into JavaScript namespaces. + +## Overview + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +The `@JS` macro supports organizing your exported Swift code into namespaces using dot-separated strings. This allows you to create hierarchical structures in JavaScript that mirror your Swift code organization. + +There are two ways to create namespaces: +1. **`@JS(namespace:)`** - Explicitly specify a namespace for functions, classes, or enums +2. **Namespace enums** - Use empty enums to create implicit namespace hierarchies (see ) + +## Functions with Namespaces + +You can export functions to specific namespaces by providing a namespace parameter: + +```swift +import JavaScriptKit + +// Export a function to a custom namespace +@JS(namespace: "MyModule.Utils") func namespacedFunction() -> String { + return "namespaced" +} +``` + +This function will be accessible in JavaScript through its namespace hierarchy in two ways: + +```javascript +// Recommended: Access via the exports object (supports multiple WASM instances) +const { createInstantiator } = await import('./path/to/bridge-js.js'); +const instantiator = await createInstantiator(options, swift); +const exports = instantiator.createExports(instance); + +const result = exports.MyModule.Utils.namespacedFunction(); +console.log(result); // "namespaced" + +// Alternative: Access via globalThis +const result = globalThis.MyModule.Utils.namespacedFunction(); +console.log(result); // "namespaced" +``` + +The generated TypeScript declaration will reflect the namespace structure: + +```typescript +declare global { + namespace MyModule { + namespace Utils { + function namespacedFunction(): string; + } + } +} +``` + +## Classes with Namespaces + +For classes, you only need to specify the namespace on the top-level class declaration. All exported methods within the class will be part of that namespace: + +```swift +import JavaScriptKit + +@JS(namespace: "__Swift.Foundation") class Greeter { + var name: String + + @JS init(name: String) { + self.name = name + } + + @JS func greet() -> String { + return "Hello, " + self.name + "!" + } + + func changeName(name: String) { + self.name = name + } +} +``` + +In JavaScript, this class is accessible through its namespace: + +```javascript +// Always available: Access via the exports object (supports multiple WASM instances) +const greeter = new exports.__Swift.Foundation.Greeter("World"); +console.log(greeter.greet()); // "Hello, World!" + +// When exposeToGlobal: true - Also available via globalThis +const greeter = new globalThis.__Swift.Foundation.Greeter("World"); +console.log(greeter.greet()); // "Hello, World!" +``` + +> Note: Global namespace access via `globalThis` is only available when `exposeToGlobal: true` is set in your `bridge-js.config.json`. See for more details. + +The generated TypeScript declaration will organize the class within its namespace: + +```typescript +declare global { + namespace __Swift { + namespace Foundation { + class Greeter { + constructor(name: string); + greet(): string; + } + } + } +} + +export type Exports = { + __Swift: { + Foundation: { + Greeter: { + new(name: string): Greeter; + } + } + } +} + +export interface Greeter extends SwiftHeapObject { + greet(): string; +} +``` + +Using namespaces can be preferable for projects with many global functions, as they help prevent naming collisions. Namespaces also provide intuitive hierarchies for organizing your exported Swift code, and they do not affect the code generated by `@JS` declarations without namespaces. diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Generating-from-TypeScript.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Generating-from-TypeScript.md new file mode 100644 index 000000000..9c0a80dc1 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Generating-from-TypeScript.md @@ -0,0 +1,419 @@ +# Generating bindings from TypeScript + +How to generate macro-annotated Swift bindings from a TypeScript declaration file (`bridge-js.d.ts`) so you don't have to write the Swift by hand. + +## Overview + +The BridgeJS plugin can read a `bridge-js.d.ts` file in your target and generate Swift code that uses the same macros as hand-written bindings (see ). + +The output is macro-annotated Swift; you can inspect the generated file at the following path to see exactly what was produced: + +``` +./build/plugins/outputs///destination/BridgeJS/BridgeJS.Macros.swift +``` + +Use this workflow when you have existing TypeScript definitions or many APIs to bind. + +> Important: This feature is still experimental. No API stability is guaranteed, and the API may change in future releases. + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +## How to generate bindings from TypeScript + +### Step 1: Configure your package + +Add the BridgeJS plugin and enable the Extern feature as described in . + +### Step 2: Create TypeScript definitions + +Create a file named `bridge-js.d.ts` in your target source directory (e.g. `Sources//bridge-js.d.ts`). Declare the JavaScript APIs you want to use in Swift: + +```typescript +export function consoleLog(message: string): void; +``` + +### Step 3: Build your package + +Run: + +```bash +swift package --swift-sdk $SWIFT_SDK_ID js +``` + +The plugin processes `bridge-js.d.ts`, generates Swift bindings (using the same macros as in ), compiles to WebAssembly, and produces JavaScript glue in `.build/plugins/PackageToJS/outputs/`. + +> Note: For larger projects, see . + +## Declaration mappings + +### Functions + +Each exported function becomes a top-level Swift function with `@JSFunction` and `throws(JSException)`. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + + /** Returns the sum of two numbers. */ + export function sum(a: number, b: number): number; + /** + * Sets the document title. + * @param title - The new title string + */ + export function setDocumentTitle(title: string): void; + ``` + } + @Column { + ```swift + // Generated Swift + + /// Returns the sum of two numbers. + @JSFunction func sum(a: Double, b: Double) throws(JSException) -> Double + + + /// Sets the document title. + /// - Parameter title: The new title string + @JSFunction func setDocumentTitle(title: String) throws(JSException) + ``` + } +} + +### Global getters + +Module-level `declare const` or top-level readonly bindings that reference a bridged type become a Swift global property with `@JSGetter`. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document) */ + export const document: Document; + ``` + } + @Column { + ```swift + // Generated Swift + /// [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document) + @JSGetter var document: Document + ``` + } +} + +### Classes + +A class becomes a Swift struct with `@JSClass`. The constructor becomes `init(...)` with `@JSFunction`. Properties become `@JSGetter`; writable properties also get `@JSSetter` as `set(_:)`. Methods become `@JSFunction`. Static methods become `static func` on the struct. All thunks throw `JSException` if the underlying JavaScript throws. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + export class Greeter { + /** A readonly field is translated with `@JSGetter` */ + readonly id: number; + + /** A read-writable field is translated with `@JSGetter` and `@JSSetter` */ + message: string; + + /** A constructor */ + constructor(id: string, name: string); + /** A method */ + greet(): string; + /** A static method */ + static createDefault(greetingId: number, locale: string): string; + } + ``` + } + @Column { + ```swift + // Generated Swift + @JSClass struct Greeter { + /// A readonly field is translated with `@JSGetter` + @JSGetter var id: Double + + /// A read-writable field is translated with `@JSGetter` and `@JSSetter` + @JSGetter var message: String + @JSSetter func setMessage(_ newValue: String) throws(JSException) + + /// A constructor + @JSFunction init(id: String, name: String) throws(JSException) + /// A method + @JSFunction func greet() throws(JSException) -> String + @JSFunction static func createDefault(_ greetingId: Double, _ locale: String) throws(JSException) -> String + } + ``` + } +} + +### Interfaces + +An interface becomes a Swift struct with `@JSClass`. No constructor. Properties and methods are bridged the same way as for classes (`@JSGetter`, `@JSSetter`, `@JSFunction`). Instances are obtained from other calls (e.g. a function that returns the interface type). + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + export interface HTMLElement { + readonly innerText: string; + className: string; + + appendChild(child: HTMLElement): void; + } + ``` + } + @Column { + ```swift + // Generated Swift + @JSClass struct HTMLElement { + @JSGetter var innerText: String + @JSGetter var className: String + @JSSetter func setClassName(_ newValue: String) throws(JSException) + @JSFunction func appendChild(_ child: HTMLElement) throws(JSException) + } + ``` + } +} + +### Type aliases + +Type aliases are resolved when generating Swift; the resolved shape is emitted, not a separate alias type. + +- **Primitive alias** (e.g. `type UserId = string`): Replaced by the underlying Swift type (e.g. `String`) everywhere it is used. +- **Object-shaped alias** (e.g. `type User = { id: string; name: string }`): The generator emits a named Swift struct with that name and the corresponding `@JSClass` / getters / setters. No constructor; use is the same as for interfaces. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + export type UserId = string; + export type User = { + readonly id: UserId; + name: string; + }; + export function getUser(): User; + ``` + } + @Column { + ```swift + // Generated Swift (UserId inlined as String) + @JSClass struct User { + @JSGetter var id: String + @JSGetter var name: String + @JSSetter func setName(_ newValue: String) throws(JSException) + } + @JSFunction func getUser() throws(JSException) -> User + ``` + } +} + +### String enums + +TypeScript enums with string literal values become Swift enums with `String` raw value and the appropriate BridgeJS protocol conformances. Usable as parameter and return types. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + export enum Theme { + light = "light", + dark = "dark", + } + + + export function setTheme(theme: Theme): void; + export function getTheme(): Theme; + ``` + } + @Column { + ```swift + // Generated Swift + enum Theme: String { + case light = "light" + case dark = "dark" + } + extension Theme: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum {} + + @JSFunction func setTheme(_ theme: Theme) throws(JSException) -> Void + @JSFunction func getTheme() throws(JSException) -> Theme + ``` + } +} + +## Type mappings + +The following mappings apply to function parameters, return types, and class/interface properties. + +### Primitives + +| TypeScript | Swift | +|------------|-------| +| `number` | `Double` | +| `string` | `String` | +| `boolean` | `Bool` | + +These appear in the function and class examples above. + +### Arrays + +`T[]` and `Array` → `[T]`. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + export function sumAll(values: number[]): number; + export function getScores(): number[]; + export function getLabels(): string[]; + export function normalize(values: Array): Array; + ``` + } + @Column { + ```swift + // Generated Swift + @JSFunction func sumAll(_ values: [Double]) throws(JSException) -> Double + @JSFunction func getScores() throws(JSException) -> [Double] + @JSFunction func getLabels() throws(JSException) -> [String] + @JSFunction func normalize(_ values: [Double]) throws(JSException) -> [Double] + ``` + } +} + +### Optional and undefined + +- **`T | null`** → Swift `Optional` (e.g. `Optional`, `Optional`, `Optional`). +- **`T | undefined`** or optional parameters → Swift `JSUndefinedOr`. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + export function parseCount(value: number | null): number | null; + export function parseLimit(value: number | undefined): number | undefined; + export function scale(factor: number, offset: number | null): number; + + export interface Payload {} + export class RequestOptions { + body: Payload | null; + + headers: Payload | undefined; + + } + ``` + } + @Column { + ```swift + // Generated Swift + @JSFunction func parseCount(_ value: Optional) throws(JSException) -> Optional + @JSFunction func parseLimit(_ value: JSUndefinedOr) throws(JSException) -> JSUndefinedOr + @JSFunction func scale(_ factor: Double, _ offset: Optional) throws(JSException) -> Double + + @JSClass struct Payload {} + @JSClass struct RequestOptions { + @JSGetter var body: Optional + @JSSetter func setBody(_ value: Optional) throws(JSException) + @JSGetter var headers: JSUndefinedOr + @JSSetter func setHeaders(_ value: JSUndefinedOr) throws(JSException) + } + ``` + } +} + +### Records (dictionaries) + +`Record` → Swift `[String: V]`. Supported value types: primitives, arrays, nested records, optional object types. Keys other than `string` (e.g. `Record`) are unsupported; such parameters become `JSObject`. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + export function applyScores(scores: Record): void; + export function getMetadata(): Record; + export function getMatrix(value: Record>): Record>; + export function getSeries(values: Record): Record; + export function lookupByIndex(values: Record): void; + ``` + } + @Column { + ```swift + // Generated Swift + @JSFunction func applyScores(_ scores: [String: Double]) throws(JSException) -> Void + @JSFunction func getMetadata() throws(JSException) -> [String: String] + @JSFunction func getMatrix(_ value: [String: [String: Double]]) throws(JSException) -> [String: [String: Double]] + @JSFunction func getSeries(_ values: [String: [Double]]) throws(JSException) -> [String: [Double]] + @JSFunction func lookupByIndex(_ values: JSObject) throws(JSException) -> Void + ``` + } +} + +### Unbridged types (JSValue, JSObject) + +Types that cannot be expressed in the bridge (e.g. `any`, unsupported generics, or `Record`) are emitted as `JSValue` or `JSObject`. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + interface Animatable { + animate(keyframes: any, options: any): any; + } + export function getAnimatable(): Animatable; + ``` + } + @Column { + ```swift + // Generated Swift + @JSClass struct Animatable { + @JSFunction func animate(_ keyframes: JSValue, _ options: JSValue) throws(JSException) -> JSValue + } + @JSFunction func getAnimatable() throws(JSException) -> Animatable + ``` + } +} + +## Name mapping + +### Invalid or special property and type names + +When a TypeScript name is not a valid Swift identifier (e.g. contains dashes, spaces, or starts with a number), or is a Swift keyword, the generator emits a Swift-safe name and uses `jsName` so the JavaScript binding remains correct. Classes whose names start with `$` are prefixed with `_` in Swift and get `@JSClass(jsName: "...")`. + +@Row { + @Column { + ```typescript + // TypeScript (bridge-js.d.ts) + interface DOMTokenList { + "data-attrib": number; + + "0": boolean; + + for: string; + + as(): void; + } + export class $jQuery { + "call-plugin"(): void; + } + ``` + } + @Column { + ```swift + // Generated Swift + @JSClass struct DOMTokenList { + @JSGetter(jsName: "data-attrib") var data_attrib: Double + @JSSetter(jsName: "data-attrib") func setData_attrib(_ value: Double) throws(JSException) + @JSGetter(jsName: "0") var _0: Bool + @JSSetter(jsName: "0") func set_0(_ value: Bool) throws(JSException) + @JSGetter var `for`: String + @JSSetter func setFor(_ value: String) throws(JSException) + @JSFunction func `as`() throws(JSException) -> Void + } + @JSClass(jsName: "$jQuery") struct _jQuery { + @JSFunction(jsName: "call-plugin") func call_plugin() throws(JSException) -> Void + } + ``` + } +} + +## Limitations + +- No first-class support for async/Promise-returning functions;. +- No generic type parameter can appear on a bridged function signature. \ No newline at end of file diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript-into-Swift.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript-into-Swift.md new file mode 100644 index 000000000..14fccbfc1 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript-into-Swift.md @@ -0,0 +1,98 @@ +# Importing JavaScript into Swift + +Learn how to make JavaScript APIs callable from your Swift code using macro-annotated bindings. + +## Overview + +> Important: This feature is still experimental. No API stability is guaranteed, and the API may change in future releases. + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/JavaScript/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +You can import JavaScript APIs into Swift in two ways: + +1. **Annotate Swift with macros** - Use `@JSFunction`, `@JSClass`, `@JSGetter`, and `@JSSetter` to declare bindings directly in Swift. No TypeScript required. Prefer this to get started. +2. **Generate bindings from TypeScript** - Use a `bridge-js.d.ts` file; the BridgeJS plugin generates the same macro-annotated Swift. See when you have existing `.d.ts` definitions or many APIs to bind. + +This guide covers the macro-based path. + +## How to import JavaScript APIs (macro path) + +### Step 1: Configure your package + +Add the BridgeJS plugin and enable the Extern feature as described in . + +### Step 2: Declare bindings in Swift with macros + +Create Swift declarations that mirror the JavaScript API you want to call. + +You can bring JavaScript into Swift in two ways: + +- **Inject at initialization**: Declare in Swift and supply the implementation in `getImports()` (e.g. a `today()` function). +- **Import from `globalThis`**: For APIs on the JavaScript global object (e.g. `console`, `document`), use `@JSGetter(from: .global)` so they are read from `globalThis` and you don't pass them in `getImports()`. + +```swift +import JavaScriptKit + +@JSFunction func today() -> String + +@JSClass struct JSConsole { + @JSFunction func log(_ message: String) throws(JSException) +} +@JSGetter(from: .global) var console: JSConsole + +@JSClass struct Document { + @JSFunction func getElementById(_ id: String) throws(JSException) -> HTMLElement + @JSFunction func createElement(_ tagName: String) throws(JSException) -> HTMLElement +} +@JSGetter(from: .global) var document: Document + +@JSClass struct HTMLElement { + @JSGetter var innerText: String + @JSSetter func setInnerText(_ newValue: String) throws(JSException) + @JSFunction func appendChild(_ child: HTMLElement) throws(JSException) +} +``` + +For full details, see , , and . + +### Step 3: Use the bindings in Swift + +Call the bound APIs from Swift: + +```swift +import JavaScriptKit + +@JS func run() { + try console.log("Hello from Swift! (\(today()))") + + let button = document.createElement("button")! + try button.setInnerText("Click Me") + let container = document.getElementById("app")! + container.appendChild(button) +} +``` + +### Step 5: Inject JavaScript implementations (if needed) + +Bindings imported from globalThis (e.g. `console`, `document`) are read at runtime and do not go in `getImports()`. Only APIs you inject at initialization must be supplied there: + +```javascript +// index.js +import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; + +const { exports } = await init({ + getImports() { + return { + today: () => new Date().toString() + }; + } +}); + +exports.run(); +``` + +## Topics + +- +- +- \ No newline at end of file diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Class.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Class.md new file mode 100644 index 000000000..4302e0e49 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Class.md @@ -0,0 +1,54 @@ +# Importing a JavaScript class or object into Swift + +This guide shows how to bind a JavaScript class (or object shape) so you can construct and use it from Swift with `@JSClass`. + +## Steps + +### 1. Declare a Swift struct with `@JSClass` + +Add a struct that mirrors the JavaScript class. Use `@JSFunction` for the initializer and for methods, and `@JSGetter` / `@JSSetter` for properties. Property setters are exposed as functions (e.g. `setMessage(_:)`) because Swift property setters cannot `throw`. + +```swift +import JavaScriptKit + +@JSClass struct Greeter { + @JSFunction init(id: String, name: String) throws(JSException) + + @JSGetter var id: String + @JSGetter var message: String + @JSSetter func setMessage(_ newValue: String) throws(JSException) + + @JSFunction func greet() throws(JSException) -> String +} +``` + +If the class is on `globalThis`, add `from: .global` to `@JSClass` and omit the type from `getImports()` in the next step. + +### 2. Wire the JavaScript side + +**If you chose injection:** Implement the class in JavaScript and pass it in `getImports()`. + +```javascript +// index.js +import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; + +class Greeter { + constructor(id, name) { /* ... */ } + get id() { /* ... */ } + get message() { /* ... */ } + set message(value) { /* ... */ } + greet() { /* ... */ } +} + +const { exports } = await init({ + getImports() { + return { Greeter }; + } +}); +``` + +**If you chose global:** Do not pass the class in `getImports()`; the runtime will resolve it from `globalThis`. + +## Macro options + +For optional parameters (`jsName`, `from`, etc.), see the API reference: ``JSClass(jsName:from:)``, ``JSFunction(jsName:from:)``, ``JSGetter(jsName:from:)``, and ``JSSetter(jsName:from:)``. diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Function.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Function.md new file mode 100644 index 000000000..64475acfa --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Function.md @@ -0,0 +1,51 @@ +# Importing a JavaScript function into Swift + +This guide shows how to bind a JavaScript function so it is callable from Swift using `@JSFunction`. + +## Steps + +### 1. Declare the function in Swift with `@JSFunction` + +Match the JavaScript name and signature. Use Swift types that bridge to the JS types you need (see ). + +```swift +import JavaScriptKit + +@JSFunction func add(_ a: Double, _ b: Double) throws(JSException) -> Double +@JSFunction func setTitle(_ title: String) throws(JSException) +``` + +To bind a function that lives on the JavaScript global object (e.g. `parseInt`, `setTimeout`), add `from: .global`. Use `jsName` when the Swift name differs from the JavaScript name - see the ``JSFunction(jsName:from:)`` API reference for options. + +### 2. Provide the implementation at initialization + +Return the corresponding function(s) in the object passed to `getImports()` when initializing the WebAssembly module. + +```javascript +// index.js +import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; + +const { exports } = await init({ + getImports() { + return { + add: (a, b) => a + b, + setTitle: (title) => { document.title = title }, + }; + } +}); +``` + +If you used `from: .global`, do not pass the function in `getImports()`; the runtime resolves it from `globalThis`. + +### 3. Handle errors + +Bound functions are `throws(JSException)`. Call them with `try` or `try?`; they throw when the JavaScript implementation throws. + +## Supported features + +| Feature | Status | +|:--|:--| +| Primitive parameter/result types (e.g. `Double`, `Bool`) | ✅ | +| `String` parameter/result type | ✅ | +| Async function | ❌ | +| Generics | ❌ | diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Variable.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Variable.md new file mode 100644 index 000000000..044ebbe52 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Variable.md @@ -0,0 +1,59 @@ +# Importing a global JavaScript variable into Swift + +This guide shows how to bind a JavaScript global variable (or any property you provide at initialization) so you can read and optionally write it from Swift using `@JSGetter` and `@JSSetter`. + +## Steps + +### 1. Declare the variable in Swift with `@JSGetter` + +Use a type that bridges to the JavaScript value (see ). For object-shaped values, use a struct conforming to the bridged type (e.g. a `@JSClass` struct). + +```swift +import JavaScriptKit + +@JSGetter(from: .global) var document: Document +@JSGetter(from: .global) var myConfig: String +``` + +To bind a variable that is not on `globalThis`, omit `from: .global` and supply the value in `getImports()` in the next step. Use `jsName` when the Swift name differs from the JavaScript property name - see the ``JSGetter(jsName:from:)`` API reference. + +### 2. Add a setter for writable variables (optional) + +If the JavaScript property is writable and you need to set it from Swift, add a corresponding `@JSSetter` function. Property setters are exposed as functions (e.g. `setMyConfig(_:)`) because Swift property setters cannot `throw`. + +```swift +@JSGetter(from: .global) var myConfig: String +@JSSetter(from: .global) func setMyConfig(_ newValue: String) throws(JSException) +``` + +### 3. Provide the value at initialization (injected only) + +If you did **not** use `from: .global`, pass the value in the object returned by `getImports()` when initializing the WebAssembly module. + +```javascript +// index.js +import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; + +const { exports } = await init({ + getImports() { + return { + myConfig: "production", + }; + } +}); +``` + +If you used `from: .global`, do not pass the variable in `getImports()`; the runtime reads it from `globalThis`. + +## Supported features + +| Feature | Status | +|:--|:--| +| Read-only global (e.g. `document`, `console`) | ✅ | +| Writable global | ✅ (`@JSSetter`) | +| Injected variable (via `getImports()`) | ✅ | + +## See also + +- ``JSGetter(jsName:from:)`` +- ``JSSetter(jsName:from:)`` diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript-into-Swift.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript-into-Swift.md deleted file mode 100644 index 853c8800d..000000000 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-TypeScript-into-Swift.md +++ /dev/null @@ -1,176 +0,0 @@ -# Importing TypeScript into Swift - -Learn how to leverage TypeScript definitions to create type-safe bindings for JavaScript APIs in your Swift code. - -## Overview - -> Important: This feature is still experimental. No API stability is guaranteed, and the API may change in future releases. - -BridgeJS enables seamless integration between Swift and JavaScript by automatically generating Swift bindings from TypeScript declaration files (`.d.ts`). This provides type-safe access to JavaScript APIs directly from your Swift code. - -The key benefits of this approach over `@dynamicMemberLookup`-based APIs include: - -- **Type Safety**: Catch errors at compile-time rather than runtime -- **IDE Support**: Get autocompletion and documentation in your Swift editor -- **Performance**: Eliminating dynamism allows us to optimize the glue code - -If you prefer keeping your project simple, you can continue using `@dynamicMemberLookup`-based APIs. - -## Getting Started - -### Step 1: Configure Your Package - -First, add the BridgeJS plugin to your Swift package by modifying your `Package.swift` file: - -```swift -// swift-tools-version:6.0 - -import PackageDescription - -let package = Package( - name: "MyApp", - dependencies: [ - .package(url: "https://github.com/swiftwasm/JavaScriptKit.git", branch: "main") - ], - targets: [ - .executableTarget( - name: "MyApp", - dependencies: ["JavaScriptKit"], - swiftSettings: [ - // This is required because the generated code depends on @_extern(wasm) - .enableExperimentalFeature("Extern") - ], - plugins: [ - // Add build plugin for processing @JS and generate Swift glue code - .plugin(name: "BridgeJS", package: "JavaScriptKit") - ] - ) - ] -) -``` - -### Step 2: Create TypeScript Definitions - -Create a file named `bridge-js.d.ts` in your target source directory (e.g. `Sources//bridge-js.d.ts`). This file defines the JavaScript APIs you want to use in Swift: - -```typescript -// Simple function -export function consoleLog(message: string): void; - -// Define a subset of DOM API you want to use -interface Document { - // Properties - title: string; - readonly body: HTMLElement; - - // Methods - getElementById(id: string): HTMLElement; - createElement(tagName: string): HTMLElement; -} - -// You can use type-level operations like `Pick` to reuse -// type definitions provided by `lib.dom.d.ts`. -interface HTMLElement extends Pick { - appendChild(child: HTMLElement): void; - // TODO: Function types on function signatures are not supported yet. - // addEventListener(event: string, handler: (event: any) => void): void; -} - -// Provide access to `document` -export function getDocument(): Document; -``` - -BridgeJS will generate Swift code that matches these TypeScript declarations. For example: - -```swift -func consoleLog(message: String) - -struct Document { - var title: String { get set } - var body: HTMLElement { get } - - func getElementById(_ id: String) -> HTMLElement - func createElement(_ tagName: String) -> HTMLElement -} - -struct HTMLElement { - var innerText: String { get set } - var className: String { get set } - - func appendChild(_ child: HTMLElement) -} - -func getDocument() -> Document -``` - -### Step 3: Build Your Package - -Build your package with the following command: - -```bash -swift package --swift-sdk $SWIFT_SDK_ID js -``` - -This command: -1. Processes your TypeScript definition files -2. Generates corresponding Swift bindings -3. Compiles your Swift code to WebAssembly -4. Produces JavaScript glue code in `.build/plugins/PackageToJS/outputs/` - -> Note: For larger projects, you may want to generate the BridgeJS code ahead of time to improve build performance. See for more information. - -### Step 4: Use the Generated Swift Bindings - -The BridgeJS plugin automatically generates Swift bindings that match your TypeScript definitions. You can now use these APIs directly in your Swift code: - -```swift -import JavaScriptKit - -@JS func run() { - // Simple function call - consoleLog("Hello from Swift!") - - // Get `document` - let document = getDocument() - - // Property access - document.title = "My Swift App" - - // Method calls - let button = document.createElement("button") - button.innerText = "Click Me" - - // TODO: Function types on function signatures are not supported yet. - // buttion.addEventListener("click") { _ in - // print("On click!") - // } - - // DOM manipulation - let container = document.getElementById("app") - container.appendChild(button) -} -``` - -### Step 5: Inject JavaScript Implementations - -The final step is to provide the actual JavaScript implementations for the TypeScript declarations you defined. You need to create a JavaScript file that initializes your WebAssembly module with the appropriate implementations: - -```javascript -// index.js -import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; - -// Initialize the WebAssembly module with JavaScript implementations -const { exports } = await init({ - getImports() { - return { - consoleLog: (message) => { - console.log(message); - }, - getDocument: () => document, - } - } -}); - -// Call the entry point of your Swift application -exports.run(); -``` diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Introducing-BridgeJS.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Introducing-BridgeJS.md new file mode 100644 index 000000000..43f778f0c --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Introducing-BridgeJS.md @@ -0,0 +1,32 @@ +# Introducing BridgeJS + +Faster, easier Swift-JavaScript bridging for WebAssembly. + +## Overview + +**BridgeJS** is a layer underneath JavaScriptKit that makes Swift-JavaScript interop **faster and easier**: you declare the shape of the API in Swift (or in TypeScript, which generates Swift), and the tool generates glue code. + +Benefits over the dynamic `JSObject` / `JSValue` APIs include: + +- **Performance** - Generated code is specialized per interface, so crossing the bridge typically costs less than using generic dynamic APIs. +- **Type safety** - Mistakes are caught at compile time instead of at runtime. +- **Easier integration** - Declarative annotations and optional TypeScript input replace manual boilerplate (closures, serializers, cached strings). + +You can still use the dynamic APIs when you need them; BridgeJS is an additional option for boundaries where you want strong typing and better performance. + +## Two directions + +BridgeJS supports both directions of the bridge: + +1. **Export Swift to JavaScript** - Expose Swift functions, classes, and types to JavaScript using the ``JS(namespace:enumStyle:)`` macro. JavaScript can then call into your Swift code. See . +2. **Import JavaScript into Swift** - Make JavaScript APIs (functions, classes, globals like `document` or `console`) callable from Swift with macros such as ``JSClass(jsName:from:)``. Start with . You can also generate the same bindings from a TypeScript file; see . + +Many apps use both: import DOM or host APIs into Swift, and export an entry point or callbacks to JavaScript. + +## Getting started + +- To **call Swift from JavaScript**: +- To **call JavaScript from Swift**: +- To **generate bindings from TypeScript**: + +All require the same package and build setup; see for configuration. diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Setting-up-BridgeJS.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Setting-up-BridgeJS.md new file mode 100644 index 000000000..99a3d5b1c --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Setting-up-BridgeJS.md @@ -0,0 +1,60 @@ +# Setting up BridgeJS + +Package and build setup required for all BridgeJS workflows + +## Overview + +BridgeJS requires the JavaScriptKit package dependency, the experimental `Extern` Swift feature, and the BridgeJS build plugin. The same configuration applies whether you are exporting Swift to JavaScript, importing JavaScript into Swift with macros, and generating bindings from a TypeScript file. + +## Package.swift + +Add the JavaScriptKit dependency, enable the Extern feature on the target that uses BridgeJS, and register the BridgeJS plugin: + +```swift +// swift-tools-version:6.0 + +import PackageDescription + +let package = Package( + name: "MyApp", + dependencies: [ + .package(url: "https://github.com/swiftwasm/JavaScriptKit.git", branch: "main") + ], + targets: [ + .executableTarget( + name: "MyApp", + dependencies: ["JavaScriptKit"], + swiftSettings: [ + .enableExperimentalFeature("Extern") + ], + plugins: [ + .plugin(name: "BridgeJS", package: "JavaScriptKit") + ] + ) + ] +) +``` + +- **Dependency**: The target must depend on `"JavaScriptKit"`. +- **Extern feature**: Required because the generated bridge code uses `@_extern(wasm)`. +- **BridgeJS plugin**: Processes macro annotations to generate glue code and, [when present, `bridge-js.d.ts`; generates JS binding Swift code](). + +## Build command + +Build the package for the JavaScript/WebAssembly SDK: + +```bash +swift package --swift-sdk $SWIFT_SDK_ID js +``` + +This command: + +1. Runs the BridgeJS plugin +2. Compiles Swift to WebAssembly and generates JavaScript glue and TypeScript type definitions. +3. Writes output to `.build/plugins/PackageToJS/outputs/Package/`. + +For package layout and how to consume the output from JavaScript, see . + +## Larger projects + +The build plugin runs on every build. For larger projects, generating bridge code ahead of time can improve build performance. See . diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md new file mode 100644 index 000000000..81a135af3 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md @@ -0,0 +1,22 @@ +# Supported Types + +Swift types and their JavaScript/TypeScript equivalents at the BridgeJS boundary. + +## Swift and JavaScript type mapping + +| Swift type | JavaScript | TypeScript | +|:--|:--|:--| +| `Int`, `UInt`, `Double`, `Float` | number | `number` | +| `String` | string | `string` | +| `Bool` | boolean | `boolean` | +| `Void` | - | `void` | +| `[T]` | array | `T[]` | +| `[String: T]` | object | `Record` | +| `Optional` | `null` or `T` | `T \| null` | +| ``JSUndefinedOr`` `` | `undefined` or `T` | `T \| undefined` | +| ``JSObject`` | object | `object` | +| ``JSValue`` | any | `any` | + +## See Also + +- diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Unsupported-Features.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Unsupported-Features.md new file mode 100644 index 000000000..7ba25f7ae --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Unsupported-Features.md @@ -0,0 +1,28 @@ +# Unsupported Features in BridgeJS + +Limitations and unsupported patterns when using BridgeJS. + +## Overview + +BridgeJS generates glue code per Swift target (module). Some patterns that are valid in Swift or TypeScript are not supported across the bridge today. This article summarizes the main limitations so you can design your APIs accordingly. + +## Type usage crossing module boundary + +BridgeJS does **not** support using a type across module boundaries in the following situations. + +### Exporting Swift: types from another Swift module + +If you have multiple Swift targets (e.g. a library and an app), you **cannot** use a type defined in one target in an exported API of another target. + +**Unsupported example:** Module `App` exports a function that takes or returns a type defined in module `Lib`: + +```swift +// In module Lib +@JS public struct LibPoint { + let x: Double + let y: Double +} + +// In module App (depends on Lib) - unsupported +@JS public func transform(_ p: LibPoint) -> LibPoint { ... } +``` diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/Debugging.md b/Sources/JavaScriptKit/Documentation.docc/Articles/Debugging.md new file mode 100644 index 000000000..a8e5d77fd --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/Debugging.md @@ -0,0 +1,81 @@ +# Debugging + +Debug your Swift applications running on JavaScript environment using DWARF-based debugging tools, including Chrome DevTools extensions and command-line debuggers. + +## Overview + +These debugging tools are DWARF-based, so you need to build your application with DWARF sections enabled. + +Build your application with debug configuration using: + +```bash +swift package --swift-sdk $SWIFT_SDK_ID js -c debug +``` + +Alternatively, you can omit the `-c debug` flag since the `js` plugin builds with debug configuration by default: + +```bash +swift package --swift-sdk $SWIFT_SDK_ID js +``` + +## Chrome DevTools + +When debugging a web browser application, Chrome DevTools provides a powerful debugging environment. It allows you to set breakpoints and step through your Swift source code at the source level. + +There are two DWARF extensions available for Chrome DevTools: an enhanced extension specifically designed for Swift, and the official C/C++ extension. For Swift development, the enhanced extension is recommended. + +> Important: The two extensions cannot coexist. You must use only one extension at a time. + +### Enhanced DWARF Extension for Swift + +For the best Swift debugging experience, use the enhanced DWARF extension that provides: + +- Breakpoint setting and Swift code inspection +- Human-readable call stack frames +- Swift variable value inspection + +![Chrome DevTools with Swift support](chrome-devtools-swift.png) + +To install this enhanced extension: + +1. If you have the official "C/C++ DevTools Support (DWARF)" extension installed, uninstall it first +2. Download the extension ZIP file from [GitHub Releases](https://github.com/GoodNotes/devtools-frontend/releases/tag/swift-0.2.3.0) +3. Go to `chrome://extensions/` and enable "Developer mode" +4. Drag and drop the downloaded ZIP file into the page + +When you close and reopen the DevTools window, DevTools will suggest reloading itself to apply settings. + +> Note: There is a known issue where some JavaScriptKit types like `JSObject` and `JSValue` are not shown in pretty format in the variables view. + +### Official DWARF Extension + +Alternatively, you can use the official [`C/C++ DevTools Support (DWARF)`](https://goo.gle/wasm-debugging-extension) extension. However, it has limitations for Swift development: + +- Function names in the stack trace are mangled (you can demangle them using `swift demangle` command) +- Variable inspection is unavailable since Swift depends on its own mechanisms instead of DWARF's structure type feature + +![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/Documentation.docc/Articles/Deploying-Pages.md b/Sources/JavaScriptKit/Documentation.docc/Articles/Deploying-Pages.md index 96789f206..435a00f53 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/Deploying-Pages.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/Deploying-Pages.md @@ -11,7 +11,7 @@ Once you've built your application with JavaScriptKit, you'll need to deploy it Build your application using [Vite](https://vite.dev/) build tool: ```bash -# Build the Swift package for WebAssembly +# Build the Swift package for WebAssembly with release configuration $ swift package --swift-sdk wasm32-unknown-wasi js -c release # Create a minimal HTML file (if you don't have one) @@ -63,7 +63,7 @@ jobs: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest - container: swift:6.0.3 + container: swift:6.2 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/FAQ.md b/Sources/JavaScriptKit/Documentation.docc/Articles/FAQ.md new file mode 100644 index 000000000..c4f22a437 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/FAQ.md @@ -0,0 +1,28 @@ +# FAQ + +Common questions about JavaScriptKit and BridgeJS. + +## Why does the initialization need to be async? Why must I await it? + +Initialization is asynchronous because the runtime must **fetch and instantiate the WebAssembly module** before your Swift code can run. That means: + +1. **Fetching** the `.wasm` binary (e.g. over the network or from disk). +2. **Instantiating** it with `WebAssembly.instantiate()` (or `instantiateStreaming()`), which compiles the module and allocates the linear memory and table. + +Until that completes, there is no WebAssembly instance to call into, so the entry point that sets up the Swift-JavaScript bridge has to be `async` and must be `await`ed from the JavaScript host (e.g. in your `index.js` or HTML script). This matches the standard WebAssembly JavaScript API, which is promise-based. + +## Why does every imported JavaScript interface via BridgeJS declare `throws(JSException)`? + +This is a conservative, safety-oriented design. Calling into JavaScript can throw at any time. If the Swift call site does not expect errors (i.e. the call is not in a `throws` context and the compiler does not force handling), then when JavaScript throws: + +- Control leaves the WebAssembly call frames **without running function epilogues**. +- Even a `do { } catch { }` in Swift does not run its `catch` block in the way you might expect, because unwinding crosses the WASM/JS boundary. +- **`defer` blocks are not executed** in those frames. + +That can lead to **inconsistent memory state** and **resource leaks**. To avoid that, every call that might invoke JavaScript is modeled as throwing: all imported JS functions, property accessors, and related operations are marked with `throws(JSException)`. That way: + +- The compiler requires you to handle or propagate errors. +- You explicitly decide how to react to JavaScript exceptions (e.g. `try`/`catch`, or propagating `throws`). +- Epilogues and cleanup run in a well-defined way when you handle the error in Swift. + +So the “everything throws” rule is there to keep behavior predictable and safe when crossing the Swift-JavaScript boundary. diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/JavaScript-Environment-Requirements.md b/Sources/JavaScriptKit/Documentation.docc/Articles/JavaScript-Environment-Requirements.md index 6483e4ca6..f0672085d 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/JavaScript-Environment-Requirements.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/JavaScript-Environment-Requirements.md @@ -1,5 +1,7 @@ # JavaScript Environment Requirements +Understand the JavaScript features required by JavaScriptKit and ensure your target environment supports them. + ## Required JavaScript Features The JavaScript package produced by the JavaScriptKit packaging plugin requires the following JavaScript features: diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/JavaScript-Interop-Cheat-Sheet.md b/Sources/JavaScriptKit/Documentation.docc/Articles/JavaScript-Interop-Cheat-Sheet.md new file mode 100644 index 000000000..4280a4637 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/JavaScript-Interop-Cheat-Sheet.md @@ -0,0 +1,376 @@ +# JavaScript Interop Cheat Sheet + +Practical recipes for manipulating JavaScript values from Swift with JavaScriptKit. Each section shows the shortest path to access, call, or convert the APIs you interact with the most. + +## Access JavaScript Values + +### Global entry points + +```swift +let global: JSObject = JSObject.global +let document: JSObject = global.document.object! +let math: JSObject = global.Math.object! +``` + +- Use ``JSObject/global`` for `globalThis` and drill into properties. +- Accessing through [dynamic member lookup](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0195-dynamic-member-lookup.md) returns ``JSValue``; call `.object`, `.number`, `.string`, etc. to unwrap a concrete type (callable values are represented as ``JSObject`` as well). +- Prefer storing ``JSObject`` references (`document` above) when you call multiple members to avoid repeated conversions (for performance). + +### Properties, subscripts, and symbols + +```swift +extension JSObject { + public subscript(_ name: String) -> JSValue { get set } + public subscript(_ index: Int) -> JSValue { get set } + public subscript(_ name: JSSymbol) -> JSValue { get set } + /// Use this API when you want to avoid repeated String serialization overhead + public subscript(_ name: JSString) -> JSValue { get set } + /// A convenience method of `subscript(_ name: String) -> JSValue` + /// to access the member through Dynamic Member Lookup. + /// ```swift + /// let document: JSObject = JSObject.global.document.object! + /// ``` + public subscript(dynamicMember name: String) -> JSValue { get set } +} +extension JSValue { + /// An unsafe convenience method of `JSObject.subscript(_ index: Int) -> JSValue` + /// - Precondition: `self` must be a JavaScript Object. + public subscript(dynamicMember name: String) -> JSValue + public subscript(_ index: Int) -> JSValue +} +``` + +**Example** + +```swift +document.title = .string("Swift <3 Web") +let obj = JSObject.global.myObject.object! +let value = obj["key"].string // Access object property with String +let propName = JSString("key") +let value2 = obj[propName].string // Access object property with JSString + +let array = JSObject.global.Array.object!.new(1, 2, 3) +array[0] = .number(10) // Assign to array index + +let symbol = JSSymbol("secret") +let data = obj[symbol].object +``` + +## Call Functions and Methods + +```swift +extension JSObject { + /// Call this function with given `arguments` using [Callable values of user-defined nominal types](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0253-callable.md) + /// ```swift + /// let alert = JSObject.global.alert.object! + /// alert("Hello from Swift") + /// ``` + public func callAsFunction(_ arguments: ConvertibleToJSValue...) -> JSValue + public func callAsFunction(this: JSObject, _ arguments: ConvertibleToJSValue...) -> JSValue + + /// Returns the `name` member method binding this object as `this` context. + public subscript(_ name: String) -> ((ConvertibleToJSValue...) -> JSValue)? { get } + public subscript(_ name: JSString) -> ((ConvertibleToJSValue...) -> JSValue)? { get } + /// A convenience method of `subscript(_ name: String) -> ((ConvertibleToJSValue...) -> JSValue)?` to access the member through Dynamic Member Lookup. + /// ```swift + /// let document = JSObject.global.document.object! + /// let divElement = document.createElement!("div") + /// ``` + public subscript(dynamicMember name: String) -> ((ConvertibleToJSValue...) -> JSValue)? { get } +} +extension JSValue { + /// An unsafe convenience method of `JSObject.subscript(_ name: String) -> ((ConvertibleToJSValue...) -> JSValue)?` + /// - Precondition: `self` must be a JavaScript Object and specified member should be a callable object. + public subscript(dynamicMember name: String) -> ((ConvertibleToJSValue...) -> JSValue) +} +``` + +**Example** + +```swift +let alert = JSObject.global.alert.object! +alert("Hello from Swift") + +let console = JSObject.global.console.object! +_ = console.log!("Cheat sheet ready", 1, true) + +let document = JSObject.global.document.object! +let button = document.createElement!("button").object! +_ = button.classList.add("primary") +``` + +- **Dynamic Member Lookup and `!`**: When calling a method on ``JSObject`` (like `createElement!`), it returns an optional closure, so `!` is used to unwrap and call it. In contrast, calling on ``JSValue`` (like `button.classList.add`) returns a non-optional closure that traps on failure for convenience. + +Need to bind manually? Grab the function object and supply `this`: + +```swift +let appendChild = document.body.appendChild.object! +appendChild(this: document.body.object!, document.createElement!("div")) +``` + +### Passing options objects + +When JavaScript APIs require an options object, create one using ``JSObject``: + +```swift +public class JSObject: ExpressibleByDictionaryLiteral { + /// Creates an empty JavaScript object (equivalent to {} or new Object()) + public init() + + /// Creates a new object with the key-value pairs in the dictionary literal + public init(dictionaryLiteral elements: (String, JSValue)...) +} +``` + +**Example** + +```swift +// Create options object with dictionary literal +let listeningOptions: JSObject = ["once": .boolean(true), "passive": .boolean(true)] +button.addEventListener!("click", handler, listeningOptions) + +// Create empty object and add properties +let fetchOptions = JSObject() +fetchOptions["method"] = .string("POST") +let headers: JSObject = ["Content-Type": .string("application/json")] +fetchOptions["headers"] = headers.jsValue +fetchOptions["body"] = "{}".jsValue + +let fetch = JSObject.global.fetch.object! +let response = fetch("https://api.example.com", fetchOptions) +``` + +### Throwing JavaScript + +JavaScript exceptions surface as ``JSException``. Wrap the function (or object) in a throwing helper. + +```swift +// Method +let JSON = JSObject.global.JSON.object! +do { + let value = try JSON.throwing.parse!("{\"flag\":true}") +} catch let error as JSException { + print("Invalid JSON", error) +} + +// Function +let validateAge: JSObject = JSObject.global.validateAge.object! +do { + try validateAge.throws(-3) +} catch let error as JSException { + print("Validation failed:", error) +} +``` + +- Use ``JSObject/throwing`` to access object methods that may throw JavaScript exceptions. +- Use ``JSObject/throws`` to call the callable object itself that may throw JavaScript exceptions. + +### Constructors and `new` + +```swift +let url = JSObject.global.URL.object!.new("https://example.com", "https://example.com") +let searchParams = url.searchParams.object! +``` + +Use ``JSThrowingFunction/new(_:)`` (via `throws.new`) when the constructor can throw. + +## Convert Between Swift and JavaScript + +### Swift -> JavaScript + +Types conforming to ``ConvertibleToJSValue`` can be converted via the `.jsValue` property. Conversion behavior depends on the context: + +| Swift type | JavaScript result | Notes | +|------------|------------------|-------| +| `Bool` | `JSValue.boolean(Bool)` | | +| `String` | `JSValue.string(JSString)` | Wrapped in ``JSString`` to avoid extra copies | +| `Int`, `UInt`, `Int8-32`, `UInt8-32`, `Float`, `Double` | `JSValue.number(Double)` | All numeric types convert to `Double` | +| `Int64`, `UInt64` | `JSValue.bigInt(JSBigInt)` | Converted to `BigInt` (requires `import JavaScriptBigIntSupport`) | +| `Data` | `Uint8Array` | Converted to `Uint8Array` (requires `import JavaScriptFoundationCompat`) | +| `Array` where `Element: ConvertibleToJSValue` | JavaScript Array | Each element converted via `.jsValue` | +| `Dictionary` where `Value: ConvertibleToJSValue` | Plain JavaScript object | Keys must be `String` | +| `Optional.none` | `JSValue.null` | Use ``JSValue/undefined`` when you specifically need `undefined` | +| `Optional.some(wrapped)` | `wrapped.jsValue` | | +| ``JSValue``, ``JSObject``, ``JSString`` | Passed through | No conversion needed | + +**Function arguments**: Automatic conversion when passing to JavaScript functions: + +```swift +let alert = JSObject.global.alert.object! +alert("Hello") // String automatically converts via .jsValue + +let console = JSObject.global.console.object! +console.log!("Count", 42, true) // All arguments auto-convert +``` + +**Property assignment**: Explicit conversion required: + +```swift +let obj = JSObject.global.myObject.object! +let count: Int = 42 +let message = "Hello" + +obj["count"] = count.jsValue +obj["message"] = message.jsValue + +obj.count = count.jsValue +obj.message = message.jsValue + +// Alternative: use JSValue static methods +obj["count"] = .number(Double(count)) +obj.message = .string(message) +divElement.innerText = .string("Count \(count)") +canvasElement.width = .number(Double(size)) +``` + +### JavaScript -> Swift + +Access JavaScript values through ``JSValue`` accessors: + +```swift +let jsValue: JSValue = // ... some JavaScript value + +// Primitive types via direct accessors (most common pattern) +let message: String? = jsValue.string +let n: Double? = jsValue.number +let flag: Bool? = jsValue.boolean +let obj: JSObject? = jsValue.object + +// Access nested properties through JSObject subscripts +if let obj = jsValue.object { + let nested = obj.key.string + let arrayItem = obj.items[0].string + let count = obj.count.number +} + +// Arrays (if elements conform to ConstructibleFromJSValue) +if let items = [String].construct(from: jsValue) { + // Use items +} + +// Dictionaries (if values conform to ConstructibleFromJSValue) +if let data = [String: Int].construct(from: jsValue) { + // Use data +} + +// For complex Decodable types, use JSValueDecoder +struct User: Decodable { + let name: String + let age: Int +} +let user = try JSValueDecoder().decode(User.self, from: jsValue) +``` + +## Pass Swift Closures back to JavaScript + +```swift +public class JSClosure: JSObject, JSClosureProtocol { + public init(_ body: @escaping (sending [JSValue]) -> JSValue) + public static func async( + priority: TaskPriority? = nil, + _ body: @escaping (sending [JSValue]) async throws(JSException) -> JSValue + ) -> JSClosure + public func release() +} + +public class JSOneshotClosure: JSObject, JSClosureProtocol { + public init(_ body: @escaping (sending [JSValue]) -> JSValue) + public static func async( + priority: TaskPriority? = nil, + _ body: @escaping (sending [JSValue]) async throws(JSException) -> JSValue + ) -> JSOneshotClosure + public func release() +} +``` + +**Example** + +```swift +let document = JSObject.global.document.object! +let console = JSObject.global.console.object! + +// Persistent closure - keep reference while JavaScript can call it +let button = document.createElement!("button").object! +let handler = JSClosure { args in + console.log!("Clicked", args[0]) + return .undefined +} +button.addEventListener!("click", handler) + +// One-shot closure - automatically released after first call +button.addEventListener!( + "click", + JSOneshotClosure { _ in + console.log!("One-off click") + return .undefined + }, + ["once": true] +) + +// Async closure - bridges Swift async to JavaScript Promise +let asyncHandler = JSClosure.async { _ async throws(JSException) -> JSValue in + try! await Task.sleep(nanoseconds: 1_000_000) + console.log!("Async closure finished") + return .undefined +} +button.addEventListener!("async", asyncHandler) +``` + +## Promises and `async/await` + +```swift +public final class JSPromise: JSBridgedClass { + public init(unsafelyWrapping object: JSObject) + public init(resolver: @escaping (@escaping (Result) -> Void) -> Void) + public static func async( + body: @escaping () async throws(JSException) -> Void + ) -> JSPromise + public static func async( + body: @escaping () async throws(JSException) -> JSValue + ) -> JSPromise + + public enum Result { + case success(JSValue) + case failure(JSValue) + } + + // Available when JavaScriptEventLoop is linked + public var value: JSValue { get async throws(JSException) } + public var result: Result { get async } +} +``` + +**Example** + +```swift +import JavaScriptEventLoop + +JavaScriptEventLoop.installGlobalExecutor() + +let console = JSObject.global.console.object! +let fetch = JSObject.global.fetch.object! + +// Wrap existing JavaScript Promise and await from Swift +Task { + do { + let response = try await JSPromise( + unsafelyWrapping: fetch("https://example.com").object! + ).value + console.log!("Fetched data", response) + } catch let error as JSException { + console.error!("Fetch failed", error.thrownValue) + } +} + +// Expose Swift async work to JavaScript +let swiftPromise = JSPromise.async { + try await Task.sleep(nanoseconds: 1_000_000_000) + return .string("Swift async complete") +} +``` + +- Wrap existing promise-returning APIs with ``JSPromise/init(unsafelyWrapping:)``. +- Use `JSPromise.async(body:)` (with `Void` or `JSValue` return type) to expose Swift `async/await` work to JavaScript callers. +- To await JavaScript `Promise` from Swift, import `JavaScriptEventLoop`, call `JavaScriptEventLoop.installGlobalExecutor()` early, and use the `value` property. +- The `value` property suspends until the promise resolves or rejects, rethrowing rejections as ``JSException``. + diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/Package-Output-Structure.md b/Sources/JavaScriptKit/Documentation.docc/Articles/Package-Output-Structure.md new file mode 100644 index 000000000..af9b0d2bd --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/Package-Output-Structure.md @@ -0,0 +1,155 @@ +# Package Output Structure + +Understand the structure and contents of the JavaScript package generated by the `swift package js` command. + +## Overview + +When you run `swift package --swift-sdk $SWIFT_SDK_ID js`, the PackageToJS plugin compiles your Swift code to WebAssembly and generates a JavaScript package in `.build/plugins/PackageToJS/outputs/Package/`. This package contains all the necessary files to run your Swift application in JavaScript environments (browser or Node.js). + +## Package Structure + +The output package has the following structure: + +``` +.build/plugins/PackageToJS/outputs/Package/ +├── ProductName.wasm # Compiled WebAssembly module +├── index.js # Main entry point for browser environments +├── index.d.ts # TypeScript type definitions for index.js +├── instantiate.js # Low-level instantiation API +├── instantiate.d.ts # TypeScript type definitions for instantiate.js +├── package.json # npm package metadata +└── platforms/ + ├── browser.js # Browser-specific platform setup + ├── browser.d.ts # TypeScript definitions for browser.js + ├── node.js # Node.js-specific platform setup + └── node.d.ts # TypeScript definitions for node.js +``` + +## Using the Package + +### In Browser + +```html + + + + + + +``` + +### In Node.js + +```javascript +import { instantiate } from './.build/plugins/PackageToJS/outputs/Package/instantiate.js'; +import { defaultNodeSetup } from './.build/plugins/PackageToJS/outputs/Package/platforms/node.js'; + +async function main() { + const options = await defaultNodeSetup(); + await instantiate(options); +} + +main(); +``` + +> Tip: For a complete Node.js setup example, see the [Node.js example](https://github.com/swiftwasm/JavaScriptKit/tree/main/Examples/NodeJS). + +### With Bundlers (Vite, Webpack, etc.) + +The generated package can be consumed by JavaScript bundlers: + +```bash +npm install .build/plugins/PackageToJS/outputs/Package +``` + +Then import it in your JavaScript code: + +```javascript +import { init } from 'package-name'; +await init(); +``` + +## Core Files + +### WebAssembly Module (`ProductName.wasm`) + +The compiled WebAssembly binary containing your Swift code. The filename matches your SwiftPM product name (e.g., `Basic.wasm` for a product named "Basic"). + +### Entry Point (`index.js`) + +The main entry point for browser environments. It provides a convenient `init()` function that handles module instantiation with default settings. + +```javascript +import { init } from './.build/plugins/PackageToJS/outputs/Package/index.js'; + +// Initialize with default browser setup +await init(); +``` + +For packages with BridgeJS imports, you can provide custom imports: + +```javascript +import { init } from './.build/plugins/PackageToJS/outputs/Package/index.js'; + +await init({ + getImports: () => ({ + // Your custom imports + }) +}); +``` + +### Instantiation API (`instantiate.js`) + +A lower-level API for more control over module instantiation. Use this when you need to customize the WebAssembly instantiation process or WASI setup. + +```javascript +import { instantiate } from './.build/plugins/PackageToJS/outputs/Package/instantiate.js'; +import { defaultBrowserSetup } from './.build/plugins/PackageToJS/outputs/Package/platforms/browser.js'; + +const options = await defaultBrowserSetup({ + module: fetch('./ProductName.wasm'), + // ... other options +}); + +const { instance, swift, exports } = await instantiate(options); +``` + +### Platform-Specific Setup + +The `platforms/` directory contains platform-specific setup functions: +- `platforms/browser.js` - Provides `defaultBrowserSetup()` for browser environments +- `platforms/node.js` - Provides `defaultNodeSetup()` for Node.js environments + +## Package Metadata (`package.json`) + +The generated `package.json` includes: + +```json +{ + "name": "package-name", + "version": "0.0.0", + "type": "module", + "private": true, + "exports": { + ".": "./index.js", + "./wasm": "./ProductName.wasm" + }, + "dependencies": { + "@bjorn3/browser_wasi_shim": "0.3.0" + } +} +``` + +The `exports` field allows importing the package as an npm dependency: + +```javascript +import { init } from '.build/plugins/PackageToJS/outputs/Package'; +``` + +## TypeScript Support + +All JavaScript files have corresponding `.d.ts` TypeScript definition files, providing full type safety when using the package in TypeScript projects. + diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/Profiling-Memory-Usage.md b/Sources/JavaScriptKit/Documentation.docc/Articles/Profiling-Memory-Usage.md new file mode 100644 index 000000000..bf14824b4 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/Profiling-Memory-Usage.md @@ -0,0 +1,37 @@ +# Profiling Memory Usage + +Profile memory usage of your Swift applications running on JavaScript environment to identify memory leaks and understand memory allocation patterns. + +## Overview + +Memory profiling helps you understand how your application uses memory, identify memory leaks, and optimize memory allocation patterns. This guide covers tools and techniques for profiling memory usage in Swift applications running on JavaScript environment. + +When profiling memory usage, start with JavaScript execution environment's heap profiler. If `WebAssembly.Memory` objects are the bottleneck, use specialized WebAssembly memory profilers that understand the Wasm instance's memory allocator. + +## Chrome DevTools Heap Snapshots + +Start by using Chrome DevTools' built-in heap profiler to understand overall memory usage in your application. See [Chrome DevTools documentation on heap snapshots](https://developer.chrome.com/docs/devtools/memory-problems/heap-snapshots) for detailed instructions. + +## wasm-memprof + +If `WebAssembly.Memory` objects are the bottleneck, JavaScript engine's default profiler typically doesn't track allocations within WebAssembly's memory space, so you won't get good insights. In such cases, use a profiler like [wasm-memprof](https://github.com/kateinoigakukun/wasm-memprof) that understands the Wasm instance's memory allocator. + +wasm-memprof is a heap profiler specifically designed for WebAssembly applications. It provides detailed memory allocation tracking with Swift symbol demangling support, helping you identify memory leaks and understand memory usage patterns within WebAssembly's linear memory. + +![wasm-memprof visualization](https://raw.githubusercontent.com/kateinoigakukun/wasm-memprof/main/docs/demo.png) + +### Setup + +Add wasm-memprof to your application before instantiating your Wasm program: + +```javascript +import { WMProf } from "wasm-memprof"; +import { SwiftDemangler } from "wasm-memprof/plugins/swift-demangler.js"; + +const swiftDemangler = SwiftDemangler.create(); +globalThis.WebAssembly = WMProf.wrap(globalThis.WebAssembly, { + demangler: swiftDemangler.demangle.bind(swiftDemangler), +}); +``` + +Check the [wasm-memprof repository](https://github.com/kateinoigakukun/wasm-memprof) for detailed documentation and examples. diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/Profiling-Performance-Issues.md b/Sources/JavaScriptKit/Documentation.docc/Articles/Profiling-Performance-Issues.md new file mode 100644 index 000000000..77ad013e1 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/Profiling-Performance-Issues.md @@ -0,0 +1,51 @@ +# Profiling Performance Issues + +Profile your Swift applications running on JavaScript environment to identify performance bottlenecks using Chrome DevTools and other profiling tools. + +## Overview + +Profiling helps you understand where your application spends time. This guide covers tools and techniques for profiling Swift applications running on JavaScript environment, focusing on performance profiling. For memory profiling, see . + +## Chrome DevTools Performance Tab + +Chrome DevTools provides a built-in Performance profiler that can help you identify performance bottlenecks in your WebAssembly application. See [Chrome DevTools documentation on performance profiling](https://developer.chrome.com/docs/devtools/performance) for detailed instructions. + +![Chrome DevTools Performance Tab](chrome-devtools-perf.png) + +> Note: WebAssembly function names may appear mangled in the performance timeline. You can use `swift demangle` to decode them, or use the enhanced DWARF extension mentioned in for better symbol resolution. + +### V8 Compilation Pipeline Considerations + +When DevTools is open, V8's WebAssembly compilation pipeline behaves differently: + +- **With DevTools open**: V8 replaces optimized TurboFan code with unoptimized Liftoff code for debugging purposes. This means performance measurements taken while DevTools is open will not reflect actual production performance. + +- **With Performance tab recording**: When you click the "Record" button in the Performance tab, code gets recompiled with TurboFan again for profiling. However, the initial tier-down to Liftoff when DevTools opens can still affect measurements. + +> Important: Do not measure FPS or performance metrics while DevTools is open, as the results will not be representative of actual production performance. Close DevTools before taking performance measurements, or use the Performance tab's recording feature which recompiles code appropriately for profiling. + +See [V8's WebAssembly compilation pipeline documentation](https://v8.dev/docs/wasm-compilation-pipeline#debugging) for more details. + +## Performance Best Practices + +### Build Configuration + +For profiling, use a release build with debug information. You have two options: + +**DWARF mode** (recommended for easier symbol resolution): + +```bash +swift package --swift-sdk $SWIFT_SDK_ID js -c release --debug-info-format dwarf +``` + +DWARF mode preserves DWARF structures, which may disable some wasm-opt optimizations. This can result in performance characteristics that differ from actual release builds. However, the DevTools extension can automatically demangle function names, making results easier to read. + +**Name section mode** (recommended for accurate performance characteristics): + +```bash +swift package --swift-sdk $SWIFT_SDK_ID js -c release --debug-info-format name +``` + +Name section mode uses WebAssembly's [name section](https://webassembly.github.io/spec/core/appendix/custom.html#name-section) and applies the same optimizations as regular release builds, providing more accurate performance characteristics. However, you'll need to manually demangle function names using `swift demangle` when analyzing results. + +> Note: The limitation of name section mode requiring manual demangling may be alleviated in the future through improvements to the DevTools extension. diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/Resources/chrome-devtools-perf.png b/Sources/JavaScriptKit/Documentation.docc/Articles/Resources/chrome-devtools-perf.png new file mode 100644 index 000000000..c26898a10 Binary files /dev/null and b/Sources/JavaScriptKit/Documentation.docc/Articles/Resources/chrome-devtools-perf.png differ diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/Resources/chrome-devtools-swift.png b/Sources/JavaScriptKit/Documentation.docc/Articles/Resources/chrome-devtools-swift.png new file mode 100644 index 000000000..cd34a311b Binary files /dev/null and b/Sources/JavaScriptKit/Documentation.docc/Articles/Resources/chrome-devtools-swift.png differ diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/Resources/chrome-devtools.png b/Sources/JavaScriptKit/Documentation.docc/Articles/Resources/chrome-devtools.png new file mode 100644 index 000000000..2498bb5a7 Binary files /dev/null and b/Sources/JavaScriptKit/Documentation.docc/Articles/Resources/chrome-devtools.png differ diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/Resources/coverage-support.png b/Sources/JavaScriptKit/Documentation.docc/Articles/Resources/coverage-support.png new file mode 100644 index 000000000..3ddd9fcb8 Binary files /dev/null and b/Sources/JavaScriptKit/Documentation.docc/Articles/Resources/coverage-support.png differ diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/Testing.md b/Sources/JavaScriptKit/Documentation.docc/Articles/Testing.md new file mode 100644 index 000000000..c3bf5e76f --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/Testing.md @@ -0,0 +1,185 @@ +# Testing + +Write and run tests for your Swift applications running on JavaScript environment using XCTest or swift-testing. + +## Overview + +JavaScriptKit supports running tests written with both XCTest and swift-testing. Tests are compiled to WebAssembly and executed in JavaScript environments (Node.js or browser). Unlike standard Swift testing, building and running tests are integrated into a single command that handles the JavaScript runtime setup. + +> Note: See the [Testing example](https://github.com/swiftwasm/JavaScriptKit/tree/main/Examples/Testing) for a complete working example. + +## Setting Up Tests + +### Package Configuration + +Your `Package.swift` should have a test target with a dependency on your library target. Here's a simple example: + +```swift +// swift-tools-version: 6.2 + +import PackageDescription + +let package = Package( + name: "Example", + products: [ + .library(name: "Example", targets: ["Example"]), + ], + dependencies: [ + .package(url: "https://github.com/swiftwasm/JavaScriptKit.git", branch: "main") + ], + targets: [ + .target( + name: "Example", + dependencies: [ + .product(name: "JavaScriptKit", package: "JavaScriptKit") + ] + ), + .testTarget( + name: "ExampleTests", + dependencies: [ + "Example", + .product(name: "JavaScriptEventLoopTestSupport", package: "JavaScriptKit"), + ] + ), + ] +) +``` + +> Important: Include `JavaScriptEventLoopTestSupport` in your test target dependencies. This is required to run tests in the JavaScript event loop environment. + +### Writing Tests + +Create your test files in the `Tests/ExampleTests` directory. JavaScriptKit supports both XCTest and swift-testing. Write your tests using either framework as you would for standard Swift projects. + +## Running Tests + +### Basic Test Execution + +Run your tests using the `js test` subcommand: + +```bash +swift package --disable-sandbox --swift-sdk $SWIFT_SDK_ID js test +``` + +> Important: The `--disable-sandbox` flag is required because the test runner needs to execute npm and Playwright to run tests in JavaScript environments. + +This command will: +1. Build your test target as WebAssembly +2. Package the tests with the necessary JavaScript runtime +3. Execute the tests in Node.js by default + +The test binary is produced as `PackageTests.wasm` (where `Package` is your package name) and is located in `.build/plugins/PackageToJS/outputs/PackageTests/`. + +### Test Environment Options + +**Run tests in Node.js (default):** + +```bash +swift package --disable-sandbox --swift-sdk $SWIFT_SDK_ID js test --environment node +``` + +**Run tests in a browser:** + +```bash +swift package --disable-sandbox --swift-sdk $SWIFT_SDK_ID js test --environment browser +``` + +When running tests in the browser, the command will launch a browser instance using Playwright and execute the tests there. + +### Other Test Options + +**Build tests without running them:** + +```bash +swift package --disable-sandbox --swift-sdk $SWIFT_SDK_ID js test --build-only +``` + +After building, you can run the tests manually: + +```bash +node .build/plugins/PackageToJS/outputs/PackageTests/bin/test.js +``` + +**List available tests:** + +```bash +swift package --disable-sandbox --swift-sdk $SWIFT_SDK_ID js test --list-tests +``` + +**Filter tests by name:** + +```bash +swift package --disable-sandbox --swift-sdk $SWIFT_SDK_ID js test --filter "testTrivial" +``` + +**Enable inspector for browser tests:** + +```bash +swift package --disable-sandbox --swift-sdk $SWIFT_SDK_ID js test --environment browser --inspect +``` + +This starts a local server without automatically running tests. You can manually open `http://localhost:3000/test.browser.html` in your browser to run the tests and use the browser's DevTools for debugging. + +## Code Coverage + +To generate code coverage reports: + +1. **Run tests with code coverage enabled:** + +```bash +swift package --disable-sandbox --swift-sdk $SWIFT_SDK_ID js test --enable-code-coverage +``` + +2. **Generate HTML coverage report:** + +```bash +llvm-cov show -instr-profile=.build/plugins/PackageToJS/outputs/PackageTests/default.profdata \ + --format=html .build/plugins/PackageToJS/outputs/PackageTests/main.wasm \ + -o .build/coverage/html Sources +``` + +3. **View the coverage report:** + +```bash +npx serve .build/coverage/html +``` + +![Code coverage report](coverage-support.png) + +## Customizing Test Execution + +You can customize the test harness by importing the generated test function and calling it with custom options: + +```javascript +// run-tests-custom.mjs +import { testBrowser } from "./.build/plugins/PackageToJS/outputs/PackageTests/test.js"; + +async function runTest(args) { + const exitCode = await testBrowser({ + args: args, + playwright: { + browser: "chromium", + launchOptions: { + headless: false, + } + } + }); + if (exitCode !== 0) { + process.exit(exitCode); + } +} + +// Run XCTest test suites +await runTest([]); + +// Run Swift Testing test suites +await runTest(["--testing-library", "swift-testing"]); + +process.exit(0); +``` + +Then run your custom test script: + +```bash +node run-tests-custom.mjs +``` diff --git a/Sources/JavaScriptKit/Documentation.docc/Documentation.md b/Sources/JavaScriptKit/Documentation.docc/Documentation.md index 0a4109166..097203f50 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Documentation.md +++ b/Sources/JavaScriptKit/Documentation.docc/Documentation.md @@ -51,18 +51,37 @@ Check out the [examples](https://github.com/swiftwasm/JavaScriptKit/tree/main/Ex ### Articles +- +- - - +- +- +- +- +- ### BridgeJS -- +- +- - +- +- +- +- - - +- +- +- ``JS(namespace:enumStyle:)`` +- ``JSFunction(jsName:from:)`` +- ``JSClass(jsName:from:)`` +- ``JSGetter(jsName:from:)`` +- ``JSSetter(jsName:from:)`` ### Core APIs - ``JSValue`` - ``JSObject`` -- ``JS(namespace:)`` +- ``JS(namespace:enumStyle:)`` diff --git a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Hello-World.tutorial b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Hello-World.tutorial index c054e3a48..021960501 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Hello-World.tutorial +++ b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Hello-World.tutorial @@ -1,4 +1,4 @@ -@Tutorial(time: 5) { +@Tutorial(time: 30) { @Intro(title: "Quick Start: Hello World") { This tutorial walks you through creating a simple web application using JavaScriptKit. You'll learn how to set up a Swift package, add JavaScriptKit as a dependency, write code to manipulate the DOM, and build and run your web application. @@ -6,19 +6,35 @@ } @Section(title: "Prerequisites") { - Visit the [installation guide](https://book.swiftwasm.org/getting-started/setup.html) to install the Swift SDK for WebAssembly before starting this tutorial. - This tutorial assumes you have the Swift SDK for WebAssembly installed. Please check your Swift installation. + This tutorial requires the OSS Swift Toolchain and Swift SDK for WebAssembly to be installed. Follow these steps to set up your development environment for building web applications with JavaScriptKit. @Steps { @Step { - Check your Swift toolchain version. If you see different - @Code(name: "Console", file: "hello-world-0-1-swift-version.txt") + Install `swiftly`, the Swift toolchain installer, per the [instructions on swift.org](https://www.swift.org/install/) for your platform. + + `swiftly` is the recommended way to install and manage OSS Swift toolchains. You cannot use toolchains bundled with Xcode for WebAssembly development. + @Code(name: "Console", file: "hello-world-0-0-install-swiftly.txt") + } + + @Step { + Install the latest Swift 6.2 development snapshot using `swiftly`: + + @Code(name: "Console", file: "hello-world-0-1-install-toolchain.txt") } + + @Step { + Install the Swift SDK for WASI that matches your toolchain version: + + Navigate to [the downloads page](https://www.swift.org/download/) and find the "Swift SDK for WASI" section. Find a version that **exactly** matches the toolchain version from step 2. + + @Code(name: "Console", file: "hello-world-0-2-install-sdk.txt") + } + @Step { - Select a Swift SDK for WebAssembly version that matches the version of the Swift toolchain you have installed. + Verify the Swift SDK installation and set up your environment: The following sections of this tutorial assume you have set the `SWIFT_SDK_ID` environment variable. - @Code(name: "Console", file: "hello-world-0-2-select-sdk.txt") + @Code(name: "Console", file: "hello-world-0-3-verify-sdk.txt") } } } @@ -98,4 +114,4 @@ } } } -} +} diff --git a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-0-install-swiftly.txt b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-0-install-swiftly.txt new file mode 100644 index 000000000..96abdfc4f --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-0-install-swiftly.txt @@ -0,0 +1,9 @@ +# Install swiftly per the instructions for your platform +# Visit https://www.swift.org/install/ for platform-specific instructions + +# Example for macOS: +$ curl -O https://download.swift.org/swiftly/darwin/swiftly.pkg && \ +installer -pkg swiftly.pkg -target CurrentUserHomeDirectory && \ +~/.swiftly/bin/swiftly init --quiet-shell-followup && \ +. "${SWIFTLY_HOME_DIR:-$HOME/.swiftly}/env.sh" && \ +hash -r diff --git a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-1-install-toolchain.txt b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-1-install-toolchain.txt new file mode 100644 index 000000000..8e2941014 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-1-install-toolchain.txt @@ -0,0 +1,14 @@ +# Install latest 6.2 development snapshot +$ swiftly install 6.2.1 +Installing Swift 6.2.1... +Swift 6.2.1 installed successfully. + +# Select the installed toolchain +$ swiftly use 6.2.1 +Using Swift 6.2.1 + +# Verify the toolchain is active +$ swift --version +Apple Swift version 6.2.1 (swift-6.2.1-RELEASE) +or +Swift version 6.2.1 (swift-6.2.1-RELEASE) diff --git a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-1-swift-version.txt b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-1-swift-version.txt deleted file mode 100644 index 5d5ad28df..000000000 --- a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-1-swift-version.txt +++ /dev/null @@ -1,7 +0,0 @@ -$ swift --version -Apple Swift version 6.0.3 (swift-6.0.3-RELEASE) -or -Swift version 6.0.3 (swift-6.0.3-RELEASE) - -$ swift sdk list -6.0.3-RELEASE-wasm32-unknown-wasi diff --git a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-2-install-sdk.txt b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-2-install-sdk.txt new file mode 100644 index 000000000..7127316d1 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-2-install-sdk.txt @@ -0,0 +1,6 @@ +# Navigate to https://www.swift.org/download/ and find the "Swift SDK for WASI" section +# Find a URL that exactly matches your toolchain version from the previous step +# Press "Copy install command" to get the installation command + +# Example installation command (replace with the exact command from swift.org): +$ swift sdk install https://download.swift.org/swift-6.2.1-release/wasm-sdk/swift-6.2.1-RELEASE/swift-6.2.1-RELEASE_wasm.artifactbundle.tar.gz --checksum 482b9f95462b87bedfafca94a092cf9ec4496671ca13b43745097122d20f18af diff --git a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-2-select-sdk.txt b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-2-select-sdk.txt deleted file mode 100644 index b5fc2c620..000000000 --- a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-2-select-sdk.txt +++ /dev/null @@ -1,9 +0,0 @@ -$ swift --version -Apple Swift version 6.0.3 (swift-6.0.3-RELEASE) -or -Swift version 6.0.3 (swift-6.0.3-RELEASE) - -$ swift sdk list -6.0.3-RELEASE-wasm32-unknown-wasi - -$ export SWIFT_SDK_ID=6.0.3-RELEASE-wasm32-unknown-wasi diff --git a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-3-verify-sdk.txt b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-3-verify-sdk.txt new file mode 100644 index 000000000..10d256ec1 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-0-3-verify-sdk.txt @@ -0,0 +1,8 @@ +# Verify the Swift SDK was installed +$ swift sdk list +swift-6.2.1-RELEASE_wasm +swift-6.2.1-RELEASE_wasm-embedded + +# In this tutorial, we use non-embedded SDK. +# Set the SDK ID as an environment variable for convenience +$ export SWIFT_SDK_ID=swift-6.2.1-RELEASE_wasm diff --git a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-1-2-add-dependency.txt b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-1-2-add-dependency.txt index 358629d0c..f5b88a17a 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-1-2-add-dependency.txt +++ b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-1-2-add-dependency.txt @@ -5,5 +5,5 @@ Creating .gitignore Creating Sources/ Creating Sources/main.swift -$ swift package add-dependency https://github.com/swiftwasm/JavaScriptKit.git --branch main +$ swift package add-dependency https://github.com/swiftwasm/JavaScriptKit.git --from Updating package manifest at Package.swift... done. diff --git a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-1-3-add-target-dependency.txt b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-1-3-add-target-dependency.txt index 317690412..02dda64cb 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-1-3-add-target-dependency.txt +++ b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-1-3-add-target-dependency.txt @@ -5,7 +5,7 @@ Creating .gitignore Creating Sources/ Creating Sources/main.swift -$ swift package add-dependency https://github.com/swiftwasm/JavaScriptKit.git --branch main +$ swift package add-dependency https://github.com/swiftwasm/JavaScriptKit.git --from Updating package manifest at Package.swift... done. $ swift package add-target-dependency --package JavaScriptKit JavaScriptKit Hello diff --git a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-2-1-main-swift.swift b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-2-1-main-swift.swift index a528e65b1..b8e5041dd 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-2-1-main-swift.swift +++ b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-2-1-main-swift.swift @@ -1,6 +1,6 @@ import JavaScriptKit let document = JSObject.global.document -var div = document.createElement("div") +let div = document.createElement("div") div.innerText = "Hello from Swift!" -document.body.appendChild(div) +_ = document.body.appendChild(div) diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSBigInt.swift b/Sources/JavaScriptKit/FundamentalObjects/JSBigInt.swift index 3f0c2632b..aaa462201 100644 --- a/Sources/JavaScriptKit/FundamentalObjects/JSBigInt.swift +++ b/Sources/JavaScriptKit/FundamentalObjects/JSBigInt.swift @@ -1,6 +1,6 @@ import _CJavaScriptKit -private var constructor: JSFunction { JSObject.global.BigInt.function! } +private var constructor: JSObject { JSObject.global.BigInt.object! } /// A wrapper around [the JavaScript `BigInt` /// class](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSClosure.swift b/Sources/JavaScriptKit/FundamentalObjects/JSClosure.swift index d290046ab..b3e80e66f 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 ) } @@ -49,6 +55,8 @@ public class JSOneshotClosure: JSObject, JSClosureProtocol { /// - Parameters: /// - priority: The priority of the new unstructured Task created under the hood. /// - body: The Swift function to call asynchronously. + /// - file: The file identifier where the function is defined. + /// - line: The line number where the function is defined. @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) public static func async( priority: TaskPriority? = nil, @@ -65,6 +73,8 @@ public class JSOneshotClosure: JSObject, JSClosureProtocol { /// - taskExecutor: The executor preference of the new unstructured Task created under the hood. /// - priority: The priority of the new unstructured Task created under the hood. /// - body: The Swift function to call asynchronously. + /// - file: The file identifier where the function is defined. + /// - line: The line number where the function is defined. @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) public static func async( executorPreference taskExecutor: (any TaskExecutor)? = nil, @@ -103,21 +113,35 @@ public class JSOneshotClosure: JSObject, JSClosureProtocol { /// button.removeEventListener!("click", JSValue.function(eventListener)) /// ``` /// -public class JSClosure: JSFunction, JSClosureProtocol { +public class JSClosure: JSObject, JSClosureProtocol { class SharedJSClosure { // Note: 6.0 compilers built with assertions enabled crash when calling // `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 } } } @@ -146,7 +170,11 @@ public class JSClosure: JSFunction, 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) @@ -157,7 +185,12 @@ public class JSClosure: JSFunction, 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") @@ -171,6 +204,8 @@ public class JSClosure: JSFunction, JSClosureProtocol { /// - Parameters: /// - priority: The priority of the new unstructured Task created under the hood. /// - body: The Swift function to call asynchronously. + /// - file: The file identifier where the function is defined. + /// - line: The line number where the function is defined. @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) public static func async( priority: TaskPriority? = nil, @@ -187,6 +222,8 @@ public class JSClosure: JSFunction, JSClosureProtocol { /// - taskExecutor: The executor preference of the new unstructured Task created under the hood. /// - priority: The priority of the new unstructured Task created under the hood. /// - body: The Swift function to call asynchronously. + /// - file: The file identifier where the function is defined. + /// - line: The line number where the function is defined. @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) public static func async( executorPreference taskExecutor: (any TaskExecutor)? = nil, @@ -208,6 +245,97 @@ public class JSClosure: JSFunction, JSClosureProtocol { #endif } +/// Heap storage for typed closures generated by BridgeJS. +/// +/// The storage is owned by the JavaScript closure and keeps the call-site metadata +/// so that calls after `release()` can report a helpful error. +@_spi(BridgeJS) public final class _BridgeJSTypedClosureBox: _BridgedSwiftClosureBox { + @_spi(BridgeJS) public var closure: Signature + var isManuallyReleased: Bool = false + + init(_ closure: Signature) { + self.closure = closure + } +} + +/// A typed handle to a JavaScript closure generated by BridgeJS. +/// +/// Use `JSTypedClosure` when you need to pass a Swift closure to JavaScript and then +/// manage its lifetime explicitly from Swift. You must call `release()` when the closure +/// is no longer needed. After releasing, any attempt to invoke the closure from JavaScript +/// throws a `JSException` (no crash), including a file/line message pointing to where the +/// typed closure was created. +/// +/// The underlying JavaScript function is also registered with a `FinalizationRegistry` as a +/// safety net to release the Swift closure storage if `release()` is forgotten, but this +/// is non-deterministic and should not be relied on for timely cleanup. +/// +/// ```swift +/// @JSFunction func someJSFunction(_ c: JSTypedClosure<(Int) -> Int>) throws(JSException) +/// let closure = JSTypedClosure<(Int) -> Int> { $0 + 1 } +/// defer { closure.release() } +/// try someJSFunction(closure) +/// ``` +public struct JSTypedClosure { + private let storage: _BridgeJSTypedClosureBox + private let _jsObject: JSObject + + @_spi(BridgeJS) + public init( + makeClosure: (_ pointer: UnsafeMutableRawPointer, _ fileID: UnsafePointer, _ line: UInt32) -> Int32, + body: Signature, + fileID: StaticString, + line: UInt32 + ) { + let storage = _BridgeJSTypedClosureBox(body) + // NOTE: Perform an unbalanced retain to give the closure box storage ownership + // to the JavaScript side. It will be balanced by two code paths: + // + // 1. When the JS closure made by `makeClosure` is GC'ed, the FinalizationRegistry + // will call `_bjs_release_swift_closure` to release the closure box storage. + // 2. When Swift side manually calls `release()` on the closure, it will release + // the closure box storage. + let pointer = Unmanaged.passRetained(storage).toOpaque() + let id = makeClosure(pointer, fileID.utf8Start, line) + self._jsObject = JSObject(id: UInt32(bitPattern: id)) + self.storage = storage + } + + @_spi(BridgeJS) + public func bridgeJSLowerParameter() -> Int32 { + return _jsObject.bridgeJSLowerParameter() + } + + @_spi(BridgeJS) + public func bridgeJSLowerReturn() -> Int32 { + return _jsObject.bridgeJSLowerReturn() + } + + /// The underlying JavaScript function handle. + /// + /// Use this when you need to store or compare the JS function identity on the JavaScript side. + public var jsObject: JSObject { _jsObject } + + /// Releases the Swift closure storage owned by this typed closure. + /// + /// Call this exactly once when the closure is no longer needed by JavaScript. + /// After release, any attempt to invoke the closure from JavaScript throws a `JSException` + /// describing a call on a released `JSTypedClosure`. + /// Calling `release()` multiple times has no effect. + public func release() { + guard !storage.isManuallyReleased else { + // Already manually released + return + } + storage.isManuallyReleased = true + // Unregister the closure from the FinalizationRegistry because we here decrement + // the refcount of the storage, so the finalizer won't be responsible for releasing it. + _swift_js_closure_unregister(Int32(bitPattern: _jsObject.id)) + // Balance the retain given to the JavaScript side + Unmanaged.passUnretained(storage).release() + } +} + #if compiler(>=5.5) && (!hasFeature(Embedded) || os(WASI)) @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) private func makeAsyncClosure( @@ -309,15 +437,23 @@ 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`. @@ -78,7 +81,7 @@ public class JSFunction: JSObject { /// ``` /// /// ```swift - /// let validateAge = JSObject.global.validateAge.function! + /// let validateAge = JSObject.global.validateAge.object! /// try validateAge.throws(20) /// ``` public var `throws`: JSThrowingFunction { @@ -91,8 +94,22 @@ public class JSFunction: 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))) } @@ -104,27 +121,81 @@ public class JSFunction: JSObject { fatalError("unavailable") } - override public var jsValue: JSValue { - .function(self) - } - 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 b9330ae80..caacd49f2 100644 --- a/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift +++ b/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift @@ -16,8 +16,8 @@ import _CJavaScriptKit /// reference counting system. @dynamicMemberLookup public class JSObject: Equatable, ExpressibleByDictionaryLiteral { - internal static var constructor: JSFunction { _constructor.wrappedValue } - private static let _constructor = LazyThreadLocal(initialize: { JSObject.global.Object.function! }) + internal static var constructor: JSObject { _constructor.wrappedValue } + private static let _constructor = LazyThreadLocal(initialize: { JSObject.global.Object.object! }) @usableFromInline internal var _id: JavaScriptObjectRef @@ -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 } } @@ -174,7 +190,7 @@ public class JSObject: Equatable, ExpressibleByDictionaryLiteral { } /// Access the `symbol` member dynamically through JavaScript and Swift runtime bridge library. - /// - Parameter symbol: The name of this object's member to access. + /// - Parameter name: The name of this object's member to access. /// - Returns: The value of the `name` member of this object. public subscript(_ name: JSSymbol) -> JSValue { get { @@ -213,7 +229,7 @@ public class JSObject: Equatable, ExpressibleByDictionaryLiteral { /// Return `true` if this value is an instance of the passed `constructor` function. /// - Parameter constructor: The constructor function to check. /// - Returns: The result of `instanceof` in the JavaScript environment. - public func isInstanceOf(_ constructor: JSFunction) -> Bool { + public func isInstanceOf(_ constructor: JSObject) -> Bool { assertOnOwnerThread(hint: "calling 'isInstanceOf'") return swjs_instanceof(id, constructor.id) } @@ -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, @@ -258,8 +274,6 @@ public class JSObject: Equatable, ExpressibleByDictionaryLiteral { return nil case .object(let object): return object as? Self - case .function(let function): - return function as? Self case .symbol(let symbol): return symbol as? Self case .bigInt(let bigInt): diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSSymbol.swift b/Sources/JavaScriptKit/FundamentalObjects/JSSymbol.swift index a9461317b..dbf801759 100644 --- a/Sources/JavaScriptKit/FundamentalObjects/JSSymbol.swift +++ b/Sources/JavaScriptKit/FundamentalObjects/JSSymbol.swift @@ -1,7 +1,7 @@ import _CJavaScriptKit -private let _Symbol = LazyThreadLocal(initialize: { JSObject.global.Symbol.function! }) -private var Symbol: JSFunction { _Symbol.wrappedValue } +private let _Symbol = LazyThreadLocal(initialize: { JSObject.global.Symbol.object! }) +private var Symbol: JSObject { _Symbol.wrappedValue } /// A wrapper around [the JavaScript `Symbol` /// class](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Symbol) diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift b/Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift index aee17fd69..94b5b0eca 100644 --- a/Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift +++ b/Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift @@ -4,8 +4,8 @@ import _CJavaScriptKit /// A `JSFunction` wrapper that enables throwing function calls. /// Exceptions produced by JavaScript functions will be thrown as `JSValue`. public class JSThrowingFunction { - private let base: JSFunction - public init(_ base: JSFunction) { + private let base: JSObject + public init(_ base: JSObject) { self.base = base } @@ -73,10 +73,19 @@ public class JSThrowingFunction { } private func invokeJSFunction( - _ jsFunc: JSFunction, + _ jsFunc: JSObject, 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/JSBridgedType.swift b/Sources/JavaScriptKit/JSBridgedType.swift index 92739079e..bb23cc00c 100644 --- a/Sources/JavaScriptKit/JSBridgedType.swift +++ b/Sources/JavaScriptKit/JSBridgedType.swift @@ -13,10 +13,23 @@ extension JSBridgedType { public var description: String { jsValue.description } } +/// A protocol that Swift classes that are exposed to JavaScript via `@JS class` conform to. +/// +/// The conformance is automatically synthesized by `@JSClass` for BridgeJS-generated declarations. +public protocol _JSBridgedClass { + /// The JavaScript object wrapped by this instance. + /// You may assume that `jsObject instanceof Self.constructor == true` + var jsObject: JSObject { get } + + /// Create an instance wrapping the given JavaScript object. + /// You may assume that `jsObject instanceof Self.constructor` + init(unsafelyWrapping jsObject: JSObject) +} + /// Conform to this protocol when your Swift class wraps a JavaScript class. -public protocol JSBridgedClass: JSBridgedType { +public protocol JSBridgedClass: JSBridgedType, _JSBridgedClass { /// The constructor function for the JavaScript class - static var constructor: JSFunction? { get } + static var constructor: JSObject? { get } /// The JavaScript object wrapped by this instance. /// You may assume that `jsObject instanceof Self.constructor == true` 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/JSUndefinedOr.swift b/Sources/JavaScriptKit/JSUndefinedOr.swift new file mode 100644 index 000000000..de7be09b4 --- /dev/null +++ b/Sources/JavaScriptKit/JSUndefinedOr.swift @@ -0,0 +1,56 @@ +/// A wrapper that represents a JavaScript value of `Wrapped | undefined`. +/// +/// In BridgeJS, `Optional` is bridged as `Wrapped | null`. +/// Use `JSUndefinedOr` when the JavaScript API expects +/// `Wrapped | undefined` instead. +@frozen public enum JSUndefinedOr { + /// The JavaScript value is `undefined`. + case undefined + /// The JavaScript value is present and wrapped. + case value(Wrapped) + + /// Creates a wrapper from a Swift optional. + /// + /// - Parameter optional: The optional value to wrap. + /// `nil` becomes ``undefined`` and a non-`nil` value becomes ``value(_:)``. + @inlinable + public init(optional: Wrapped?) { + self = optional.map(Self.value) ?? .undefined + } + + /// Returns the wrapped value as a Swift optional. + /// + /// Returns `nil` when this value is ``undefined``. + @inlinable + public var asOptional: Wrapped? { + switch self { + case .undefined: + return nil + case .value(let wrapped): + return wrapped + } + } +} + +extension JSUndefinedOr: ConstructibleFromJSValue where Wrapped: ConstructibleFromJSValue { + public static func construct(from value: JSValue) -> Self? { + if value.isUndefined { return .undefined } + guard let wrapped = Wrapped.construct(from: value) else { return nil } + return .value(wrapped) + } +} + +extension JSUndefinedOr: ConvertibleToJSValue where Wrapped: ConvertibleToJSValue { + public var jsValue: JSValue { + switch self { + case .undefined: + return .undefined + case .value(let wrapped): + return wrapped.jsValue + } + } +} + +// MARK: - BridgeJS (via _BridgedAsOptional in BridgeJSIntrinsics) + +extension JSUndefinedOr: _BridgedAsOptional {} diff --git a/Sources/JavaScriptKit/JSValue.swift b/Sources/JavaScriptKit/JSValue.swift index b9f8dd4a7..6c02e73f6 100644 --- a/Sources/JavaScriptKit/JSValue.swift +++ b/Sources/JavaScriptKit/JSValue.swift @@ -2,21 +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 function(JSFunction) - 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 } @@ -36,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 } @@ -45,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 } @@ -54,25 +88,19 @@ 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 } } - /// Returns the `JSFunction` of this JS value if its type is function. - /// If not, returns `nil`. - public var function: JSFunction? { - switch self { - case .function(let function): return function - default: return nil - } - } + // @available(*, deprecated, renamed: "object", message: "Use the .object property instead") + public var function: JSObject? { object } /// 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 } @@ -81,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 } @@ -90,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 } } @@ -139,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. @@ -168,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( @@ -178,31 +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 { .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) } } @@ -271,14 +302,12 @@ extension JSValue { /// Returns `false` for everything except objects and functions. /// - Parameter constructor: The constructor function to check. /// - Returns: The result of `instanceof` in the JavaScript environment. - public func isInstanceOf(_ constructor: JSFunction) -> Bool { - switch self { + public func isInstanceOf(_ constructor: JSObject) -> Bool { + switch storage { case .boolean, .string, .number, .null, .undefined, .symbol, .bigInt: return false case .object(let ref): return ref.isInstanceOf(constructor) - case .function(let ref): - return ref.isInstanceOf(constructor) } } } @@ -287,7 +316,7 @@ extension JSValue: CustomStringConvertible { public var description: String { // per https://tc39.es/ecma262/multipage/text-processing.html#sec-string-constructor-string-value // this always returns a string - JSObject.global.String.function!(self).string! + JSObject.global.String.object!(self).string! } } diff --git a/Sources/JavaScriptKit/JSValueDecoder.swift b/Sources/JavaScriptKit/JSValueDecoder.swift index 08e29915c..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 } @@ -243,6 +247,7 @@ public class JSValueDecoder { /// /// - Parameter T: The type of the value to decode. /// - Parameter value: The `JSValue` to decode from. + /// - Parameter userInfo: Additional information to pass to the decoder. public func decode( _: T.Type = T.self, from value: JSValue, diff --git a/Sources/JavaScriptKit/Macros.swift b/Sources/JavaScriptKit/Macros.swift index dac264ff9..67b3488bf 100644 --- a/Sources/JavaScriptKit/Macros.swift +++ b/Sources/JavaScriptKit/Macros.swift @@ -1,3 +1,18 @@ +/// Controls how Swift enums annotated with `@JS` are emitted to TypeScript. +/// - `const`: Emit the current BridgeJS style: a `const` object with literal members plus a type alias. +/// - `tsEnum`: Emit a TypeScript `enum` declaration (only valid for simple enums and raw-value enums with String or numeric raw types). +public enum JSEnumStyle: String { + case const + 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: @@ -90,7 +105,101 @@ /// /// - Parameter namespace: A dot-separated string that defines the namespace hierarchy in JavaScript. /// Each segment becomes a nested object in the resulting JavaScript structure. +/// - Parameter enumStyle: Controls how enums are emitted to TypeScript for this declaration: +/// use `.const` (default) to emit a const object + type alias, +/// or `.tsEnum` to emit a TypeScript `enum`. +/// `.tsEnum` is supported for case enums and raw-value enums with String or numeric raw types. +/// Bool raw-value enums are not supported with `.tsEnum` and will produce an error. /// /// - Important: This feature is still experimental. No API stability is guaranteed, and the API may change in future releases. @attached(peer) -public macro JS(namespace: String? = nil) = Builtin.ExternalMacro +public macro JS(namespace: String? = nil, enumStyle: JSEnumStyle = .const) = Builtin.ExternalMacro + +/// A macro that generates a Swift getter that reads a value from JavaScript. +/// +/// 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 +/// import JavaScriptKit +/// +/// @JSGetter var count: Int +/// +/// struct Greeter { +/// @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) +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. +/// +/// This macro is used by BridgeJS-generated Swift declarations. +/// +/// - Parameter jsName: An optional string that specifies the name of the JavaScript property to write to. +/// If not provided, automatically derived from the Swift property name. (e.g. "setName" -> "name") +/// +/// Example: +/// +/// ```swift +/// import JavaScriptKit +/// +/// @JSSetter func setName(_ value: String) throws (JSException) +/// ``` +@attached(body) +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. +/// +/// This macro is used by BridgeJS-generated Swift declarations. +/// +/// Example: +/// +/// ```swift +/// import JavaScriptKit +/// +/// @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) +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. +/// +/// This macro is used by BridgeJS-generated Swift declarations. +/// +/// Example: +/// +/// ```swift +/// import JavaScriptKit +/// +/// @JSClass +/// struct JsGreeter { +/// @JSGetter var name: String +/// @JSSetter func setName(_ value: String) throws (JSException) +/// @JSFunction init(_ name: String) throws (JSException) +/// @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: named(jsObject), named(init(unsafelyWrapping:))) +@attached(extension, conformances: _JSBridgedClass) +public macro JSClass(jsName: String? = nil, from: JSImportFrom? = nil) = + #externalMacro(module: "BridgeJSMacros", type: "JSClassMacro") diff --git a/Sources/_CJavaScriptKit/include/BridgeJSInstrincics.h b/Sources/_CJavaScriptKit/include/BridgeJSInstrincics.h deleted file mode 100644 index 4f5ba93cb..000000000 --- a/Sources/_CJavaScriptKit/include/BridgeJSInstrincics.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _CJavaScriptKit_BridgeJSInstrincics_h -#define _CJavaScriptKit_BridgeJSInstrincics_h - -#include -#include "WasmGlobalMacros.h" - -#if __wasm__ -WASM_GLOBAL_DEFINE_INLINE_ACCESSORS(_swift_js_exception, i32, int32_t) -#endif - -#endif diff --git a/Sources/_CJavaScriptKit/include/BridgeJSIntrinsics.h b/Sources/_CJavaScriptKit/include/BridgeJSIntrinsics.h new file mode 100644 index 000000000..f396d1f23 --- /dev/null +++ b/Sources/_CJavaScriptKit/include/BridgeJSIntrinsics.h @@ -0,0 +1,13 @@ +#ifndef _CJavaScriptKit_BridgeJSIntrinsics_h +#define _CJavaScriptKit_BridgeJSIntrinsics_h + +#include +#include "WasmGlobalMacros.h" + +#if __wasm__ +// Global thread-local pointer storage for temporarily storing JS exceptions +// thrown from imported JavaScript functions. +WASM_GLOBAL_DEFINE_INLINE_ACCESSORS(_swift_js_exception, i32, int32_t) +#endif + +#endif diff --git a/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h b/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h index 7cb37e289..28e7b5e3d 100644 --- a/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h +++ b/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h @@ -24,7 +24,6 @@ typedef enum __attribute__((enum_extensibility(closed))) { JavaScriptValueKindObject = 3, JavaScriptValueKindNull = 4, JavaScriptValueKindUndefined = 5, - JavaScriptValueKindFunction = 6, JavaScriptValueKindSymbol = 7, JavaScriptValueKindBigInt = 8, } JavaScriptValueKind; diff --git a/Sources/_CJavaScriptKit/include/module.modulemap b/Sources/_CJavaScriptKit/include/module.modulemap index 3afe12831..f2d3c162e 100644 --- a/Sources/_CJavaScriptKit/include/module.modulemap +++ b/Sources/_CJavaScriptKit/include/module.modulemap @@ -1,5 +1,5 @@ module _CJavaScriptKit { header "_CJavaScriptKit.h" - header "BridgeJSInstrincics.h" + header "BridgeJSIntrinsics.h" export * } diff --git a/Tests/BridgeJSGlobalTests/Generated/BridgeJS.swift b/Tests/BridgeJSGlobalTests/Generated/BridgeJS.swift new file mode 100644 index 000000000..03fe0983a --- /dev/null +++ b/Tests/BridgeJSGlobalTests/Generated/BridgeJS.swift @@ -0,0 +1,316 @@ +// bridge-js: skip +// 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(BridgeJS) import JavaScriptKit + +extension GlobalNetworking.API.CallMethod: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> GlobalNetworking.API.CallMethod { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> GlobalNetworking.API.CallMethod { + return GlobalNetworking.API.CallMethod(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .get + case 1: + self = .post + case 2: + self = .put + case 3: + self = .delete + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .get: + return 0 + case .post: + return 1 + case .put: + return 2 + case .delete: + return 3 + } + } +} + +extension GlobalConfiguration.PublicLogLevel: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension GlobalConfiguration.AvailablePort: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Internal.SupportedServerMethod: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Internal.SupportedServerMethod { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Internal.SupportedServerMethod { + return Internal.SupportedServerMethod(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .get + case 1: + self = .post + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .get: + return 0 + case .post: + return 1 + } + } +} + +@_expose(wasm, "bjs_GlobalStaticPropertyNamespace_static_namespaceProperty_get") +@_cdecl("bjs_GlobalStaticPropertyNamespace_static_namespaceProperty_get") +public func _bjs_GlobalStaticPropertyNamespace_static_namespaceProperty_get() -> Void { + #if arch(wasm32) + let ret = GlobalStaticPropertyNamespace.namespaceProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_GlobalStaticPropertyNamespace_static_namespaceProperty_set") +@_cdecl("bjs_GlobalStaticPropertyNamespace_static_namespaceProperty_set") +public func _bjs_GlobalStaticPropertyNamespace_static_namespaceProperty_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + GlobalStaticPropertyNamespace.namespaceProperty = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_GlobalStaticPropertyNamespace_static_namespaceConstant_get") +@_cdecl("bjs_GlobalStaticPropertyNamespace_static_namespaceConstant_get") +public func _bjs_GlobalStaticPropertyNamespace_static_namespaceConstant_get() -> Void { + #if arch(wasm32) + let ret = GlobalStaticPropertyNamespace.namespaceConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_GlobalStaticPropertyNamespace_NestedProperties_static_nestedProperty_get") +@_cdecl("bjs_GlobalStaticPropertyNamespace_NestedProperties_static_nestedProperty_get") +public func _bjs_GlobalStaticPropertyNamespace_NestedProperties_static_nestedProperty_get() -> Int32 { + #if arch(wasm32) + let ret = GlobalStaticPropertyNamespace.NestedProperties.nestedProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_GlobalStaticPropertyNamespace_NestedProperties_static_nestedProperty_set") +@_cdecl("bjs_GlobalStaticPropertyNamespace_NestedProperties_static_nestedProperty_set") +public func _bjs_GlobalStaticPropertyNamespace_NestedProperties_static_nestedProperty_set(_ value: Int32) -> Void { + #if arch(wasm32) + GlobalStaticPropertyNamespace.NestedProperties.nestedProperty = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_GlobalStaticPropertyNamespace_NestedProperties_static_nestedConstant_get") +@_cdecl("bjs_GlobalStaticPropertyNamespace_NestedProperties_static_nestedConstant_get") +public func _bjs_GlobalStaticPropertyNamespace_NestedProperties_static_nestedConstant_get() -> Void { + #if arch(wasm32) + let ret = GlobalStaticPropertyNamespace.NestedProperties.nestedConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_GlobalStaticPropertyNamespace_NestedProperties_static_nestedDouble_get") +@_cdecl("bjs_GlobalStaticPropertyNamespace_NestedProperties_static_nestedDouble_get") +public func _bjs_GlobalStaticPropertyNamespace_NestedProperties_static_nestedDouble_get() -> Float64 { + #if arch(wasm32) + let ret = GlobalStaticPropertyNamespace.NestedProperties.nestedDouble + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_GlobalStaticPropertyNamespace_NestedProperties_static_nestedDouble_set") +@_cdecl("bjs_GlobalStaticPropertyNamespace_NestedProperties_static_nestedDouble_set") +public func _bjs_GlobalStaticPropertyNamespace_NestedProperties_static_nestedDouble_set(_ value: Float64) -> Void { + #if arch(wasm32) + GlobalStaticPropertyNamespace.NestedProperties.nestedDouble = Double.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TestHTTPServer_init") +@_cdecl("bjs_TestHTTPServer_init") +public func _bjs_TestHTTPServer_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = GlobalNetworking.API.TestHTTPServer() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TestHTTPServer_call") +@_cdecl("bjs_TestHTTPServer_call") +public func _bjs_TestHTTPServer_call(_ _self: UnsafeMutableRawPointer, _ method: Int32) -> Void { + #if arch(wasm32) + GlobalNetworking.API.TestHTTPServer.bridgeJSLiftParameter(_self).call(_: GlobalNetworking.API.CallMethod.bridgeJSLiftParameter(method)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TestHTTPServer_deinit") +@_cdecl("bjs_TestHTTPServer_deinit") +public func _bjs_TestHTTPServer_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension GlobalNetworking.API.TestHTTPServer: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_TestHTTPServer_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSGlobalTests", name: "bjs_TestHTTPServer_wrap") +fileprivate func _bjs_TestHTTPServer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_TestHTTPServer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_TestInternalServer_init") +@_cdecl("bjs_TestInternalServer_init") +public func _bjs_TestInternalServer_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Internal.TestInternalServer() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TestInternalServer_call") +@_cdecl("bjs_TestInternalServer_call") +public func _bjs_TestInternalServer_call(_ _self: UnsafeMutableRawPointer, _ method: Int32) -> Void { + #if arch(wasm32) + Internal.TestInternalServer.bridgeJSLiftParameter(_self).call(_: Internal.SupportedServerMethod.bridgeJSLiftParameter(method)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TestInternalServer_deinit") +@_cdecl("bjs_TestInternalServer_deinit") +public func _bjs_TestInternalServer_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Internal.TestInternalServer: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_TestInternalServer_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSGlobalTests", name: "bjs_TestInternalServer_wrap") +fileprivate func _bjs_TestInternalServer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_TestInternalServer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_PublicConverter_init") +@_cdecl("bjs_PublicConverter_init") +public func _bjs_PublicConverter_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = GlobalUtils.PublicConverter() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PublicConverter_toString") +@_cdecl("bjs_PublicConverter_toString") +public func _bjs_PublicConverter_toString(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + let ret = GlobalUtils.PublicConverter.bridgeJSLiftParameter(_self).toString(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PublicConverter_deinit") +@_cdecl("bjs_PublicConverter_deinit") +public func _bjs_PublicConverter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension GlobalUtils.PublicConverter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_PublicConverter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSGlobalTests", name: "bjs_PublicConverter_wrap") +fileprivate func _bjs_PublicConverter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_PublicConverter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif \ No newline at end of file diff --git a/Tests/BridgeJSGlobalTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSGlobalTests/Generated/JavaScript/BridgeJS.json new file mode 100644 index 000000000..e7bcf59b6 --- /dev/null +++ b/Tests/BridgeJSGlobalTests/Generated/JavaScript/BridgeJS.json @@ -0,0 +1,542 @@ +{ + "exported" : { + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_TestHTTPServer_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_TestHTTPServer_call", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "call", + "namespace" : [ + "GlobalNetworking", + "API" + ], + "parameters" : [ + { + "label" : "_", + "name" : "method", + "type" : { + "caseEnum" : { + "_0" : "GlobalNetworking.API.CallMethod" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "TestHTTPServer", + "namespace" : [ + "GlobalNetworking", + "API" + ], + "properties" : [ + + ], + "swiftCallName" : "GlobalNetworking.API.TestHTTPServer" + }, + { + "constructor" : { + "abiName" : "bjs_TestInternalServer_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_TestInternalServer_call", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "call", + "namespace" : [ + "GlobalNetworking", + "APIV2", + "Internal" + ], + "parameters" : [ + { + "label" : "_", + "name" : "method", + "type" : { + "caseEnum" : { + "_0" : "Internal.SupportedServerMethod" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "TestInternalServer", + "namespace" : [ + "GlobalNetworking", + "APIV2", + "Internal" + ], + "properties" : [ + + ], + "swiftCallName" : "Internal.TestInternalServer" + }, + { + "constructor" : { + "abiName" : "bjs_PublicConverter_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_PublicConverter_toString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "toString", + "namespace" : [ + "GlobalUtils" + ], + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "PublicConverter", + "namespace" : [ + "GlobalUtils" + ], + "properties" : [ + + ], + "swiftCallName" : "GlobalUtils.PublicConverter" + } + ], + "enums" : [ + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "GlobalNetworking", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "GlobalNetworking", + "tsFullPath" : "GlobalNetworking" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "API", + "namespace" : [ + "GlobalNetworking" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "GlobalNetworking.API", + "tsFullPath" : "GlobalNetworking.API" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "get" + }, + { + "associatedValues" : [ + + ], + "name" : "post" + }, + { + "associatedValues" : [ + + ], + "name" : "put" + }, + { + "associatedValues" : [ + + ], + "name" : "delete" + } + ], + "emitStyle" : "const", + "name" : "CallMethod", + "namespace" : [ + "GlobalNetworking", + "API" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "GlobalNetworking.API.CallMethod", + "tsFullPath" : "GlobalNetworking.API.CallMethod" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "GlobalConfiguration", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "GlobalConfiguration", + "tsFullPath" : "GlobalConfiguration" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "debug", + "rawValue" : "debug" + }, + { + "associatedValues" : [ + + ], + "name" : "info", + "rawValue" : "info" + }, + { + "associatedValues" : [ + + ], + "name" : "warning", + "rawValue" : "warning" + }, + { + "associatedValues" : [ + + ], + "name" : "error", + "rawValue" : "error" + } + ], + "emitStyle" : "const", + "name" : "PublicLogLevel", + "namespace" : [ + "GlobalConfiguration" + ], + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "GlobalConfiguration.PublicLogLevel", + "tsFullPath" : "GlobalConfiguration.PublicLogLevel" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "http", + "rawValue" : "80" + }, + { + "associatedValues" : [ + + ], + "name" : "https", + "rawValue" : "443" + }, + { + "associatedValues" : [ + + ], + "name" : "development", + "rawValue" : "3000" + } + ], + "emitStyle" : "const", + "name" : "AvailablePort", + "namespace" : [ + "GlobalConfiguration" + ], + "rawType" : "Int", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "GlobalConfiguration.AvailablePort", + "tsFullPath" : "GlobalConfiguration.AvailablePort" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Internal", + "namespace" : [ + "GlobalNetworking", + "APIV2" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Internal", + "tsFullPath" : "GlobalNetworking.APIV2.Internal" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "get" + }, + { + "associatedValues" : [ + + ], + "name" : "post" + } + ], + "emitStyle" : "const", + "name" : "SupportedServerMethod", + "namespace" : [ + "GlobalNetworking", + "APIV2", + "Internal" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Internal.SupportedServerMethod", + "tsFullPath" : "GlobalNetworking.APIV2.Internal.SupportedServerMethod" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "GlobalStaticPropertyNamespace", + "staticMethods" : [ + + ], + "staticProperties" : [ + { + "isReadonly" : false, + "isStatic" : true, + "name" : "namespaceProperty", + "namespace" : [ + "GlobalStaticPropertyNamespace" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "GlobalStaticPropertyNamespace" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "namespaceConstant", + "namespace" : [ + "GlobalStaticPropertyNamespace" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "GlobalStaticPropertyNamespace" + } + }, + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "GlobalStaticPropertyNamespace", + "tsFullPath" : "GlobalStaticPropertyNamespace" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "NestedProperties", + "namespace" : [ + "GlobalStaticPropertyNamespace" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + { + "isReadonly" : false, + "isStatic" : true, + "name" : "nestedProperty", + "namespace" : [ + "GlobalStaticPropertyNamespace", + "NestedProperties" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "GlobalStaticPropertyNamespace.NestedProperties" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "nestedConstant", + "namespace" : [ + "GlobalStaticPropertyNamespace", + "NestedProperties" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "GlobalStaticPropertyNamespace.NestedProperties" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "nestedDouble", + "namespace" : [ + "GlobalStaticPropertyNamespace", + "NestedProperties" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "GlobalStaticPropertyNamespace.NestedProperties" + } + }, + "type" : { + "double" : { + + } + } + } + ], + "swiftCallName" : "GlobalStaticPropertyNamespace.NestedProperties", + "tsFullPath" : "GlobalStaticPropertyNamespace.NestedProperties" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "GlobalUtils", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "GlobalUtils", + "tsFullPath" : "GlobalUtils" + } + ], + "exposeToGlobal" : true, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "BridgeJSGlobalTests" +} \ No newline at end of file diff --git a/Tests/BridgeJSGlobalTests/GlobalAPITests.swift b/Tests/BridgeJSGlobalTests/GlobalAPITests.swift new file mode 100644 index 000000000..19087ff55 --- /dev/null +++ b/Tests/BridgeJSGlobalTests/GlobalAPITests.swift @@ -0,0 +1,78 @@ +import XCTest +import JavaScriptKit + +@_extern(wasm, module: "BridgeJSGlobalTests", name: "runJsWorksGlobal") +@_extern(c) +func runJsWorksGlobal() -> Void + +// Minimal set of @JS declarations for testing globalThis access +// These are namespaced items that should be accessible via globalThis + +@JS enum GlobalNetworking { + @JS enum API { + @JS enum CallMethod { + case get + case post + case put + case delete + } + @JS class TestHTTPServer { + @JS init() {} + @JS func call(_ method: CallMethod) {} + } + } +} + +@JS enum GlobalConfiguration { + @JS enum PublicLogLevel: String { + case debug = "debug" + case info = "info" + case warning = "warning" + case error = "error" + } + + @JS enum AvailablePort: Int { + case http = 80 + case https = 443 + case development = 3000 + } +} + +@JS(namespace: "GlobalNetworking.APIV2") +enum Internal { + @JS enum SupportedServerMethod { + case get + case post + } + @JS class TestInternalServer { + @JS init() {} + @JS func call(_ method: SupportedServerMethod) {} + } +} + +@JS enum GlobalStaticPropertyNamespace { + @JS nonisolated(unsafe) static var namespaceProperty: String = "namespace" + @JS static let namespaceConstant: String = "constant" + + @JS enum NestedProperties { + @JS nonisolated(unsafe) static var nestedProperty: Int = 999 + @JS static let nestedConstant: String = "nested" + @JS nonisolated(unsafe) static var nestedDouble: Double = 1.414 + } +} + +@JS enum GlobalUtils { + @JS class PublicConverter { + @JS init() {} + + @JS func toString(value: Int) -> String { + return String(value) + } + } +} + +class GlobalAPITests: XCTestCase { + func testGlobalAccess() { + runJsWorksGlobal() + } +} diff --git a/Tests/BridgeJSGlobalTests/bridge-js.config.json b/Tests/BridgeJSGlobalTests/bridge-js.config.json new file mode 100644 index 000000000..b1b556981 --- /dev/null +++ b/Tests/BridgeJSGlobalTests/bridge-js.config.json @@ -0,0 +1,3 @@ +{ + "exposeToGlobal": true +} \ No newline at end of file diff --git a/Tests/BridgeJSGlobalTests/bridge-js.d.ts b/Tests/BridgeJSGlobalTests/bridge-js.d.ts new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/BridgeJSRuntimeTests/ClosureSupportTests.swift b/Tests/BridgeJSRuntimeTests/ClosureSupportTests.swift new file mode 100644 index 000000000..8078ed777 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/ClosureSupportTests.swift @@ -0,0 +1,290 @@ +import XCTest +import JavaScriptKit + +@JSClass struct ClosureSupportImports { + + @JSFunction static func jsApplyVoid(_ callback: JSTypedClosure<() -> Void>) throws(JSException) + @JSFunction static func jsApplyBool(_ callback: JSTypedClosure<() -> Bool>) throws(JSException) -> Bool + @JSFunction static func jsApplyInt( + _ value: Int, + _ transform: JSTypedClosure<(Int) -> Int> + ) throws(JSException) -> Int + @JSFunction static func jsApplyDouble( + _ value: Double, + _ transform: JSTypedClosure<(Double) -> Double> + ) throws(JSException) -> Double + @JSFunction static func jsApplyString( + _ value: String, + _ transform: JSTypedClosure<(String) -> String> + ) throws(JSException) -> String + // @JSFunction static func jsApplyJSValue( + // _ value: JSValue, + // _ transform: JSTypedClosure<(JSValue) -> JSValue> + // ) throws(JSException) -> JSValue + @JSFunction static func jsApplyJSObject( + _ value: JSObject, + _ transform: JSTypedClosure<(JSObject) -> JSObject> + ) throws(JSException) -> JSObject + // @JSFunction static func jsApplyArrayInt( + // _ value: [Int], + // _ transform: JSTypedClosure<([Int]) -> [Int]> + // ) throws(JSException) -> [Int] + // @JSFunction static func jsApplyArrayDouble( + // _ value: [Double], + // _ transform: JSTypedClosure<([Double]) -> [Double]> + // ) throws(JSException) -> [Double] + // @JSFunction static func jsApplyArrayString( + // _ value: [String], + // _ transform: JSTypedClosure<([String]) -> [String]> + // ) throws(JSException) -> [String] + // @JSFunction static func jsApplyArrayJSValue( + // _ value: [JSValue], + // _ transform: JSTypedClosure<([JSValue]) -> [JSValue]> + // ) throws(JSException) -> [JSValue] + // @JSFunction static func jsApplyArrayJSObject( + // _ value: [JSObject], + // _ transform: JSTypedClosure<([JSObject]) -> [JSObject]> + // ) throws(JSException) -> [JSObject] + + @JSFunction static func jsMakeIntToInt(_ base: Int) throws(JSException) -> (Int) -> Int + @JSFunction static func jsMakeDoubleToDouble(_ base: Double) throws(JSException) -> (Double) -> Double + @JSFunction static func jsMakeStringToString(_ `prefix`: String) throws(JSException) -> (String) -> String + + @JSFunction static func jsCallTwice( + _ value: Int, + _ callback: JSTypedClosure<(Int) -> Void> + ) throws(JSException) -> Int + @JSFunction static func jsCallBinary(_ callback: JSTypedClosure<(Int, Int) -> Int>) throws(JSException) -> Int + @JSFunction static func jsCallTriple(_ callback: JSTypedClosure<(Int, Int, Int) -> Int>) throws(JSException) -> Int + @JSFunction static func jsCallAfterRelease(_ callback: JSTypedClosure<() -> Void>) throws(JSException) -> String + @JSFunction static func jsOptionalInvoke(_ callback: JSTypedClosure<() -> Bool>?) throws(JSException) -> Bool + @JSFunction static func jsStoreClosure(_ callback: JSTypedClosure<() -> Void>) throws(JSException) + @JSFunction static func jsCallStoredClosure() throws(JSException) + @JSFunction static func jsHeapCount() throws(JSException) -> Int + + @JSFunction static func runJsClosureSupportTests() throws(JSException) +} + +@JS class ClosureSupportExports { + @JS static func makeIntToInt(_ base: Int) -> (Int) -> Int { + return { $0 + base } + } + @JS static func makeDoubleToDouble(_ base: Double) -> (Double) -> Double { + return { $0 + base } + } + @JS static func makeStringToString(_ prefix: String) -> (String) -> String { + return { prefix + $0 } + } + + @JS static func makeJSIntToInt(_ base: Int) -> JSTypedClosure<(Int) -> Int> { + return JSTypedClosure { $0 + base } + } + @JS static func makeJSDoubleToDouble(_ base: Double) -> JSTypedClosure<(Double) -> Double> { + return JSTypedClosure { $0 + base } + } + @JS static func makeJSStringToString(_ prefix: String) -> JSTypedClosure<(String) -> String> { + return JSTypedClosure { prefix + $0 } + } +} + +final class ClosureSupportTests: XCTestCase { + + func testRunJsClosureSupportTests() throws { + try ClosureSupportImports.runJsClosureSupportTests() + } + + func testClosureParameterVoidToVoid() throws { + var called = false + let transform = JSTypedClosure<() -> Void> { + called = true + } + defer { transform.release() } + try ClosureSupportImports.jsApplyVoid(transform) + XCTAssertTrue(called) + } + + func testClosureParameterBoolToBool() throws { + let transform = JSTypedClosure<() -> Bool> { true } + defer { transform.release() } + let result = try ClosureSupportImports.jsApplyBool(transform) + XCTAssertTrue(result) + } + + func testClosureParameterIntToInt() throws { + let transform = JSTypedClosure { $0 * 2 } + defer { transform.release() } + let result = try ClosureSupportImports.jsApplyInt(21, transform) + XCTAssertEqual(result, 42) + } + + func testClosureParameterDoubleToDouble() throws { + let transform = JSTypedClosure<(Double) -> Double> { $0 * 2 } + defer { transform.release() } + let result = try ClosureSupportImports.jsApplyDouble(21.0, transform) + XCTAssertEqual(result, 42.0) + } + + func testClosureParameterStringToString() throws { + let transform = JSTypedClosure { (value: String) in + value + ", world!" + } + defer { transform.release() } + let result = try ClosureSupportImports.jsApplyString("Hello", transform) + XCTAssertEqual(result, "Hello, world!") + } + + // func testClosureParameterJSValueToJSValue() throws { + // let transform = JSTypedClosure<(JSValue) -> JSValue> { $0 } + // defer { transform.release() } + // let result = try JSTypedClosureImports.jsApplyJSValue(.number(1), transform) + // XCTAssertEqual(result, .number(1)) + // } + + func testClosureParameterJSObjectToJSObject() throws { + let transform = JSTypedClosure<(JSObject) -> JSObject> { $0 } + defer { transform.release() } + let obj = JSObject() + let result = try ClosureSupportImports.jsApplyJSObject(obj, transform) + XCTAssertEqual(result, obj) + } + + // func testClosureParameterArrayIntToArrayInt() throws { + // let transform = JSTypedClosure<([Int]) -> [Int]> { $0 } + // defer { transform.release() } + // let result = try ClosureSupportImports.jsApplyArrayInt([1, 2, 3], transform) + // XCTAssertEqual(result, [1, 2, 3]) + // } + + // func testClosureParameterArrayDoubleToArrayDouble() throws { + // let transform = JSTypedClosure<([Double]) -> [Double]> { $0 } + // defer { transform.release() } + // let result = try ClosureSupportImports.jsApplyArrayDouble([1.0, 2.0, 3.0], transform) + // XCTAssertEqual(result, [1.0, 2.0, 3.0]) + // } + + // func testClosureParameterArrayStringToArrayString() throws { + // let transform = JSTypedClosure<([String]) -> [String]> { $0 } + // defer { transform.release() } + // let result = try ClosureSupportImports.jsApplyArrayString(["a", "b", "c"], transform) + // XCTAssertEqual(result, ["a", "b", "c"]) + // } + + // func testClosureParameterArrayJSValueToArrayJSValue() throws { + // let transform = JSTypedClosure<([JSValue]) -> [JSValue]> { $0 } + // defer { transform.release() } + // let result = try ClosureSupportImports.jsApplyArrayJSValue([.number(1), .number(2), .number(3)], transform) + // XCTAssertEqual(result, [.number(1), .number(2), .number(3)]) + // } + + // func testClosureParameterArrayJSObjectToArrayJSObject() throws { + // let transform = JSTypedClosure<([JSObject]) -> [JSObject]> { $0 } + // defer { transform.release() } + // let obj1 = JSObject() + // let obj2 = JSObject() + // let obj3 = JSObject() + // let result = try ClosureSupportImports.jsApplyArrayJSObject([obj1, obj2, obj3], transform) + // XCTAssertEqual(result, [obj1, obj2, obj3]) + // } + + func testClosureReturnIntToInt() throws { + let c = try ClosureSupportImports.jsMakeIntToInt(10) + XCTAssertEqual(c(0), 10) + XCTAssertEqual(c(32), 42) + } + + func testClosureReturnDoubleToDouble() throws { + let c = try ClosureSupportImports.jsMakeDoubleToDouble(10.0) + XCTAssertEqual(c(0.0), 10.0) + XCTAssertEqual(c(32.0), 42.0) + } + + func testClosureReturnStringToString() throws { + let c = try ClosureSupportImports.jsMakeStringToString("Hello, ") + XCTAssertEqual(c("world!"), "Hello, world!") + } + + func testClosureParameterIntToVoid() throws { + var total = 0 + let callback = JSTypedClosure<(Int) -> Void> { value in + total += value + } + defer { callback.release() } + let ret = try ClosureSupportImports.jsCallTwice(5, callback) + XCTAssertEqual(ret, 5) + XCTAssertEqual(total, 10) + } + + func testCallingReleasedClosureThrows() { + let transform = JSTypedClosure<(Int) -> Int> { $0 + 1 } + transform.release() + + do { + _ = try ClosureSupportImports.jsApplyInt(41, transform) + XCTFail("Expected JSException for released closure") + } catch let error { + let message = error.thrownValue.object?["message"].string + XCTAssertNotNil(message) + XCTAssertTrue(message?.contains(#fileID) ?? false, "message=\(message ?? "nil")") + } + } + + func testMultipleArity() throws { + let sum = JSTypedClosure<(Int, Int) -> Int> { $0 + $1 } + defer { sum.release() } + XCTAssertEqual(try ClosureSupportImports.jsCallBinary(sum), 3) + } + + func testTripleArity() throws { + let sum = JSTypedClosure<(Int, Int, Int) -> Int> { $0 + $1 + $2 } + defer { sum.release() } + XCTAssertEqual(try ClosureSupportImports.jsCallTriple(sum), 6) + } + + func testOptionalNoneSkipsCall() throws { + XCTAssertFalse(try ClosureSupportImports.jsOptionalInvoke(nil)) + } + + func testOptionalSomeCalls() throws { + var called = false + let closure = JSTypedClosure<() -> Bool> { + called = true + return true + } + defer { closure.release() } + XCTAssertTrue(try ClosureSupportImports.jsOptionalInvoke(closure)) + XCTAssertTrue(called) + } + + func testDropDuringCallThenThrows() throws { + var closure: JSTypedClosure<() -> Void>! = nil + closure = JSTypedClosure { + closure.release() + } + let message = try ClosureSupportImports.jsCallAfterRelease(closure) + XCTAssertTrue( + message.contains(#fileID), + "\"\(message)\" does not contain expected file name" + ) + } + + func testStoredClosureAfterReleaseThrows() throws { + let closure = JSTypedClosure<() -> Void> {} + try ClosureSupportImports.jsStoreClosure(closure) + closure.release() + XCTAssertThrowsError(try ClosureSupportImports.jsCallStoredClosure()) + } + + func testClosuresDoNotLeakHeapEntries() throws { + let baseline = try ClosureSupportImports.jsHeapCount() + + for _ in 0..<50 { + let closure: JSTypedClosure<(Int) -> Void> = JSTypedClosure { _ in } + _ = try? ClosureSupportImports.jsCallTwice(0, closure) + } + + // Trigger GC and read heap size from JS side + let after = try ClosureSupportImports.jsHeapCount() + XCTAssertEqual(after, baseline, "Heap entry count should return to baseline after GC") + } + +} diff --git a/Tests/BridgeJSRuntimeTests/DictionaryTests.swift b/Tests/BridgeJSRuntimeTests/DictionaryTests.swift new file mode 100644 index 000000000..95f2706e6 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/DictionaryTests.swift @@ -0,0 +1,96 @@ +@_spi(BridgeJS) import JavaScriptKit +import XCTest + +final class DictionaryTests: XCTestCase { + func testRoundTripDictionary() throws { + let input: [String: Int] = ["a": 1, "b": 2] + let result = try jsRoundTripDictionary(input) + XCTAssertEqual(result, input) + } + + func testRoundTripDictionaryBool() throws { + let input: [String: Bool] = ["yes": true, "no": false] + let result = try jsRoundTripDictionaryBool(input) + XCTAssertEqual(result, input) + } + + func testRoundTripDictionaryDouble() throws { + let input: [String: Double] = ["pi": 3.14, "tau": 6.28] + let result = try jsRoundTripDictionaryDouble(input) + XCTAssertEqual(result, input) + } + + func testRoundTripDictionaryJSObject() throws { + let global = JSObject.global + let input: [String: JSObject] = [ + "global": global + ] + let result = try jsRoundTripDictionaryJSObject(input) + XCTAssertEqual(result, input) + } + + func testRoundTripDictionaryJSValue() throws { + let input: [String: JSValue] = [ + "number": .number(123.5), + "boolean": .boolean(true), + "string": .string("hello"), + "null": .null, + ] + let result = try jsRoundTripDictionaryJSValue(input) + XCTAssertEqual(result, input) + } + + func testRoundTripNestedDictionary() throws { + let input: [String: [Double]] = [ + "xs": [1.0, 2.5], + "ys": [], + ] + let result = try jsRoundTripNestedDictionary(input) + XCTAssertEqual(result, input) + } + + func testRoundTripOptionalDictionaryNull() throws { + let some: [String: String]? = ["k": "v"] + XCTAssertEqual(try jsRoundTripOptionalDictionary(some), some) + XCTAssertNil(try jsRoundTripOptionalDictionary(nil)) + } + + func testRoundTripOptionalDictionaryUndefined() throws { + let some: JSUndefinedOr<[String: Int]> = .value(["n": 42]) + let undefined: JSUndefinedOr<[String: Int]> = .undefined + + let returnedSome = try jsRoundTripUndefinedDictionary(some) + switch returnedSome { + case .value(let dict): + XCTAssertEqual(dict, ["n": 42]) + case .undefined: + XCTFail("Expected defined dictionary") + } + + let returnedUndefined = try jsRoundTripUndefinedDictionary(undefined) + switch returnedUndefined { + case .value: + XCTFail("Expected undefined") + case .undefined: + break + } + } +} + +@JSFunction func jsRoundTripDictionary(_ values: [String: Int]) throws(JSException) -> [String: Int] + +@JSFunction func jsRoundTripDictionaryBool(_ values: [String: Bool]) throws(JSException) -> [String: Bool] + +@JSFunction func jsRoundTripDictionaryDouble(_ values: [String: Double]) throws(JSException) -> [String: Double] + +@JSFunction func jsRoundTripDictionaryJSObject(_ values: [String: JSObject]) throws(JSException) -> [String: JSObject] + +@JSFunction func jsRoundTripDictionaryJSValue(_ values: [String: JSValue]) throws(JSException) -> [String: JSValue] + +@JSFunction func jsRoundTripNestedDictionary(_ values: [String: [Double]]) throws(JSException) -> [String: [Double]] + +@JSFunction func jsRoundTripOptionalDictionary(_ values: [String: String]?) throws(JSException) -> [String: String]? + +@JSFunction func jsRoundTripUndefinedDictionary( + _ values: JSUndefinedOr<[String: Int]> +) throws(JSException) -> JSUndefinedOr<[String: Int]> diff --git a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift index 307fa21ed..97c2d5fbf 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,10 +32,59 @@ 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 } +@JS func roundTripDictionaryExport(v: [String: Int]) -> [String: Int] { + return v +} + +@JS func roundTripOptionalDictionaryExport(v: [String: String]?) -> [String: String]? { + return v +} + +@JS func roundTripJSValue(v: JSValue) -> JSValue { + return v +} + +@JS func roundTripOptionalJSValue(v: JSValue?) -> JSValue? { + return v +} + +@JS func roundTripJSValueArray(v: [JSValue]) -> [JSValue] { + return v +} + +@JS func roundTripOptionalJSValueArray(v: [JSValue]?) -> [JSValue]? { + return v +} + +@JSClass struct Foo { + @JSGetter var value: String + @JSFunction init(_ value: String) throws(JSException) +} + +@JS func makeImportedFoo(value: String) throws(JSException) -> Foo { + return try Foo(value) +} + struct TestError: Error { let message: String } @@ -59,8 +111,9 @@ struct TestError: Error { @JS func asyncRoundTripSwiftHeapObject(v: Greeter) async -> Greeter { return v } @JS func asyncRoundTripJSObject(v: JSObject) async -> JSObject { return v } -@JS class Greeter { - var name: String +@JS public class Greeter { + @JS var name: String + @JS let prefix: String = "Hello" nonisolated(unsafe) static var onDeinit: () -> Void = {} @@ -69,12 +122,33 @@ struct TestError: Error { } @JS func greet() -> String { - return "Hello, \(name)!" + return "\(prefix), \(name)!" } @JS func changeName(name: String) { self.name = name } + @JS func greetWith(greeter: Greeter, customGreeting: (Greeter) -> String) -> String { + return customGreeting(greeter) + } + + @JS func makeFormatter(suffix: String) -> (String) -> String { + return { value in "\(self.greet()) - \(value) - \(suffix)" } + } + + @JS static func makeCreator(defaultName: String) -> (String) -> Greeter { + return { name in + let fullName = name.isEmpty ? defaultName : name + return Greeter(name: fullName) + } + } + + @JS func makeCustomGreeter() -> (Greeter) -> String { + return { otherGreeter in + return "\(self.name) greets \(otherGreeter.name): \(otherGreeter.greet())" + } + } + deinit { Self.onDeinit() } @@ -101,6 +175,10 @@ struct TestError: Error { } } +@JS internal class InternalGreeter {} +@JS public class PublicGreeter {} +@JS package class PackageGreeter {} + @JS func createCalculator() -> Calculator { return Calculator() } @@ -123,6 +201,1191 @@ struct TestError: Error { return greeter.jsValue.object! } +// MARK: - Enum Tests + +@JS enum Direction { + case north + case south + case east + case west +} + +@JS enum Status { + case loading + case success + case error +} + +@JS enum Theme: String { + case light = "light" + case dark = "dark" + case auto = "auto" +} + +@JS enum HttpStatus: Int { + case ok = 200 + case notFound = 404 + case serverError = 500 + 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 + case east + case west +} + +@JS(enumStyle: .tsEnum) enum TSTheme: String { + case light = "light" + case dark = "dark" + case auto = "auto" +} + +@JS func setDirection(_ direction: Direction) -> Direction { + return direction +} + +@JS func getDirection() -> Direction { + return .north +} + +@JS func processDirection(_ input: Direction) -> Status { + switch input { + case .north, .south: return .success + case .east, .west: return .loading + } +} + +@JS func setTheme(_ theme: Theme) -> Theme { + return theme +} + +@JS func getTheme() -> Theme { + return .light +} + +@JS func setHttpStatus(_ status: HttpStatus) -> HttpStatus { + return status +} + +@JS func getHttpStatus() -> HttpStatus { + return .ok +} + +@JS func processTheme(_ theme: Theme) -> HttpStatus { + switch theme { + case .light: return .ok + case .dark: return .notFound + case .auto: return .serverError + } +} + +@JS func setTSDirection(_ direction: TSDirection) -> TSDirection { + return direction +} + +@JS func getTSDirection() -> TSDirection { + return .north +} + +@JS func setTSTheme(_ theme: TSTheme) -> TSTheme { + return theme +} + +@JS func getTSTheme() -> TSTheme { + return .light +} + +// MARK: - Namespace Enums + +@JS enum Utils { + @JS class Converter { + @JS init() {} + + @JS func toString(value: Int) -> String { + return String(value) + } + } + + @JS enum StringUtils { + @JS static func uppercase(_ text: String) -> String { + return text.uppercased() + } + + @JS static func lowercase(_ text: String) -> String { + return text.lowercased() + } + } +} + +@JS enum Networking { + @JS enum API { + @JS enum Method { + case get + case post + case put + case delete + } + @JS class HTTPServer { + @JS init() {} + @JS func call(_ method: Method) {} + } + } +} + +@JS enum Configuration { + @JS enum LogLevel: String { + case debug = "debug" + case info = "info" + case warning = "warning" + case error = "error" + } + + @JS enum Port: Int { + case http = 80 + case https = 443 + case development = 3000 + } +} + +@JS(namespace: "Networking.APIV2") +enum Internal { + @JS enum SupportedMethod { + case get + case post + } + @JS class TestServer { + @JS init() {} + @JS func call(_ method: SupportedMethod) {} + } +} + +@JS func roundtripNetworkingAPIMethod(_ method: Networking.API.Method) -> Networking.API.Method { + return method +} + +@JS func roundtripConfigurationLogLevel(_ level: Configuration.LogLevel) -> Configuration.LogLevel { + return level +} + +@JS func roundtripConfigurationPort(_ port: Configuration.Port) -> Configuration.Port { + return port +} + +@JS func processConfigurationLogLevel(_ level: Configuration.LogLevel) -> Configuration.Port { + switch level { + case .debug: return .development + case .info: return .http + case .warning: return .https + case .error: return .development + } +} + +@JS func roundtripInternalSupportedMethod(_ method: Internal.SupportedMethod) -> Internal.SupportedMethod { + return method +} + +@JS enum APIResult { + case success(String) + case failure(Int) + case flag(Bool) + case rate(Float) + case precise(Double) + case info +} + +@JS func roundtripAPIResult(result: APIResult) -> APIResult { + return result +} + +@JS func makeAPIResultSuccess(_ value: String) -> APIResult { + return .success(value) +} + +@JS func makeAPIResultFailure(_ value: Int) -> APIResult { + return .failure(value) +} + +@JS func makeAPIResultInfo() -> APIResult { + return .info +} + +@JS func makeAPIResultFlag(_ value: Bool) -> APIResult { + return .flag(value) +} + +@JS func makeAPIResultRate(_ value: Float) -> APIResult { + return .rate(value) +} + +@JS func makeAPIResultPrecise(_ value: Double) -> APIResult { + return .precise(value) +} + +@JS +enum ComplexResult { + case success(String) + case error(String, Int) + case location(Double, Double, String) + case status(Bool, Int, String) + case coordinates(Double, Double, Double) + case comprehensive(Bool, Bool, Int, Int, Double, Double, String, String, String) + case info +} + +@JS func roundtripComplexResult(_ result: ComplexResult) -> ComplexResult { + return result +} + +@JS func makeComplexResultSuccess(_ value: String) -> ComplexResult { + return .success(value) +} + +@JS func makeComplexResultError(_ message: String, _ code: Int) -> ComplexResult { + return .error(message, code) +} + +@JS func makeComplexResultLocation(_ lat: Double, _ lng: Double, _ name: String) -> ComplexResult { + return .location(lat, lng, name) +} + +@JS func makeComplexResultStatus(_ active: Bool, _ code: Int, _ message: String) -> ComplexResult { + return .status(active, code, message) +} + +@JS func makeComplexResultCoordinates(_ x: Double, _ y: Double, _ z: Double) -> ComplexResult { + return .coordinates(x, y, z) +} + +@JS func makeComplexResultComprehensive( + _ flag1: Bool, + _ flag2: Bool, + _ count1: Int, + _ count2: Int, + _ value1: Double, + _ value2: Double, + _ text1: String, + _ text2: String, + _ text3: String +) -> ComplexResult { + return .comprehensive(flag1, flag2, count1, count2, value1, value2, text1, text2, text3) +} + +@JS func makeComplexResultInfo() -> ComplexResult { + return .info +} + +@JS enum Utilities { + @JS enum Result { + case success(String) + case failure(String, Int) + case status(Bool, Int, String) + } +} + +@JS enum API { + @JS enum NetworkingResult { + case success(String) + case failure(String, Int) + } +} + +@JS func makeUtilitiesResultSuccess(_ message: String) -> Utilities.Result { + return .success(message) +} + +@JS func makeUtilitiesResultFailure(_ error: String, _ code: Int) -> Utilities.Result { + return .failure(error, code) +} + +@JS func makeUtilitiesResultStatus(_ active: Bool, _ code: Int, _ message: String) -> Utilities.Result { + return .status(active, code, message) +} + +@JS func makeAPINetworkingResultSuccess(_ message: String) -> API.NetworkingResult { + return .success(message) +} + +@JS func makeAPINetworkingResultFailure(_ error: String, _ code: Int) -> API.NetworkingResult { + return .failure(error, code) +} + +@JS func roundtripUtilitiesResult(_ result: Utilities.Result) -> Utilities.Result { + return result +} + +@JS func roundtripAPINetworkingResult(_ result: API.NetworkingResult) -> API.NetworkingResult { + return result +} + +@JS +enum AllTypesResult { + case structPayload(Address) + case classPayload(Greeter) + case jsObjectPayload(JSObject) + case nestedEnum(APIResult) + case arrayPayload([Int]) + case jsClassPayload(Foo) + case empty +} + +@JS func roundTripAllTypesResult(_ result: AllTypesResult) -> AllTypesResult { + result +} + +@JS enum TypedPayloadResult { + case precision(Precision) + case direction(Direction) + case optPrecision(Precision?) + case optDirection(Direction?) + case empty +} + +@JS func roundTripTypedPayloadResult(_ result: TypedPayloadResult) -> TypedPayloadResult { + result +} + +// MARK: - Property Tests + +// Simple class for SwiftHeapObject property testing +@JS class SimplePropertyHolder { + @JS var value: Int + + @JS init(value: Int) { + self.value = value + } +} + +// Test class for various property types +@JS class PropertyHolder { + // Primitive properties + @JS var intValue: Int + @JS var floatValue: Float + @JS var doubleValue: Double + @JS var boolValue: Bool + @JS var stringValue: String + + // Readonly primitive properties + @JS let readonlyInt: Int = 42 + @JS let readonlyFloat: Float = 3.14 + @JS let readonlyDouble: Double = 2.718281828 + @JS let readonlyBool: Bool = true + @JS let readonlyString: String = "constant" + + // JSObject property + @JS var jsObject: JSObject + + // SwiftHeapObject property + @JS var sibling: SimplePropertyHolder + + // Lazy stored property + @JS lazy var lazyValue: String = "computed lazily" + + // Computed property with getter only (readonly) + @JS var computedReadonly: Int { + return intValue * 2 + } + + // Computed property with getter and setter + @JS var computedReadWrite: String { + get { + return "Value: \(intValue)" + } + set { + // Parse the number from "Value: X" format + if let range = newValue.range(of: "Value: "), + let number = Int(String(newValue[range.upperBound...])) + { + intValue = number + } + } + } + + // Property with property observers + @JS var observedProperty: Int { + willSet { + Self.willSetCallCount += 1 + Self.lastWillSetOldValue = self.observedProperty + Self.lastWillSetNewValue = newValue + } + didSet { + Self.didSetCallCount += 1 + Self.lastDidSetOldValue = oldValue + Self.lastDidSetNewValue = self.observedProperty + } + } + + // Static properties to track observer calls + nonisolated(unsafe) static var willSetCallCount: Int = 0 + nonisolated(unsafe) static var didSetCallCount: Int = 0 + nonisolated(unsafe) static var lastWillSetOldValue: Int = 0 + nonisolated(unsafe) static var lastWillSetNewValue: Int = 0 + nonisolated(unsafe) static var lastDidSetOldValue: Int = 0 + nonisolated(unsafe) static var lastDidSetNewValue: Int = 0 + + @JS init( + intValue: Int, + floatValue: Float, + doubleValue: Double, + boolValue: Bool, + stringValue: String, + jsObject: JSObject, + sibling: SimplePropertyHolder + ) { + self.intValue = intValue + self.floatValue = floatValue + self.doubleValue = doubleValue + self.boolValue = boolValue + self.stringValue = stringValue + self.jsObject = jsObject + self.sibling = sibling + self.observedProperty = intValue // Initialize observed property + } + + @JS func getAllValues() -> String { + return "int:\(intValue),float:\(floatValue),double:\(doubleValue),bool:\(boolValue),string:\(stringValue)" + } +} + +@JS func createPropertyHolder( + intValue: Int, + floatValue: Float, + doubleValue: Double, + boolValue: Bool, + stringValue: String, + jsObject: JSObject +) -> PropertyHolder { + let sibling = SimplePropertyHolder(value: 999) + return PropertyHolder( + intValue: intValue, + floatValue: floatValue, + doubleValue: doubleValue, + boolValue: boolValue, + stringValue: stringValue, + jsObject: jsObject, + sibling: sibling + ) +} + +@JS func testPropertyHolder(holder: PropertyHolder) -> String { + return holder.getAllValues() +} + +@JS func resetObserverCounts() { + PropertyHolder.willSetCallCount = 0 + PropertyHolder.didSetCallCount = 0 + PropertyHolder.lastWillSetOldValue = 0 + PropertyHolder.lastWillSetNewValue = 0 + PropertyHolder.lastDidSetOldValue = 0 + PropertyHolder.lastDidSetNewValue = 0 +} + +@JS func getObserverStats() -> String { + return + "willSet:\(PropertyHolder.willSetCallCount),didSet:\(PropertyHolder.didSetCallCount),willSetOld:\(PropertyHolder.lastWillSetOldValue),willSetNew:\(PropertyHolder.lastWillSetNewValue),didSetOld:\(PropertyHolder.lastDidSetOldValue),didSetNew:\(PropertyHolder.lastDidSetNewValue)" +} + +// MARK: - Static Functions +@JS class MathUtils { + @JS static func add(a: Int, b: Int) -> Int { + return a + b + } + @JS class func substract(a: Int, b: Int) -> Int { + return a - b + } +} + +@JS enum StaticCalculator { + case scientific + case basic + + @JS static func roundtrip(_ value: Int) -> Int { + return value + } +} + +@JS enum StaticUtils { + @JS enum Nested { + @JS static func roundtrip(_ value: String) -> String { + return value + } + } +} + +@JS(namespace: "Services.Graph") +enum GraphOperations { + @JS static func createGraph(rootId: Int) -> Int { + return rootId * 10 + } + + @JS static func nodeCount(graphId: Int) -> Int { + return graphId + } +} + +// MARK: - Default Parameters + +@JS func testStringDefault(message: String = "Hello World") -> String { + return message +} + +@JS func testIntDefault(count: Int = 42) -> Int { + return count +} + +@JS func testBoolDefault(flag: Bool = true) -> Bool { + return flag +} + +@JS func testOptionalDefault(name: String? = nil) -> String? { + return name +} + +@JS func testMultipleDefaults( + title: String = "Default Title", + count: Int = -10, + enabled: Bool = false +) -> String { + return "\(title): \(count) (\(enabled))" +} + +@JS func testSimpleEnumDefault(status: Status = .success) -> Status { + return status +} + +@JS func testDirectionDefault(direction: Direction = .north) -> Direction { + return direction +} + +@JS func testRawStringEnumDefault(theme: Theme = .light) -> Theme { + return theme +} + +@JS func testComplexInit(greeter: Greeter = Greeter(name: "DefaultGreeter")) -> String { + return greeter.greet() +} + +@JS func testEmptyInit(_ object: StaticPropertyHolder = StaticPropertyHolder()) -> StaticPropertyHolder { + return object +} + +@JS class ConstructorDefaults { + @JS var name: String + @JS var count: Int + @JS var enabled: Bool + @JS var status: Status + @JS var tag: String? + + @JS init( + name: String = "Default", + count: Int = 42, + enabled: Bool = true, + status: Status = .success, + tag: String? = nil + ) { + self.name = name + self.count = count + self.enabled = enabled + self.status = status + self.tag = tag + } + + @JS func describe() -> String { + let tagStr = tag ?? "nil" + let statusStr: String + switch status { + case .loading: statusStr = "loading" + case .success: statusStr = "success" + case .error: statusStr = "error" + } + return "\(name):\(count):\(enabled):\(statusStr):\(tagStr)" + } +} + +@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 { + @JS static let staticConstant: String = "constant" + @JS nonisolated(unsafe) static var staticVariable: Int = 42 + @JS nonisolated(unsafe) static var staticString: String = "initial" + @JS nonisolated(unsafe) static var staticBool: Bool = true + @JS nonisolated(unsafe) static var staticFloat: Float = 3.14 + @JS nonisolated(unsafe) static var staticDouble: Double = 2.718 + + @JS static var computedProperty: String { + get { return "computed: \(staticVariable)" } + set { + if let number = Int(newValue.replacingOccurrences(of: "computed: ", with: "")) { + staticVariable = number + } + } + } + + @JS static var readOnlyComputed: Int { + return staticVariable * 2 + } + + @JS nonisolated(unsafe) static var optionalString: String? = nil + @JS nonisolated(unsafe) static var optionalInt: Int? = nil + + @JS nonisolated(unsafe) static var jsObjectProperty: JSObject = JSObject() + + @JS init() {} + +} + +@JS enum StaticPropertyEnum { + case option1 + case option2 + + @JS nonisolated(unsafe) static var enumProperty: String = "enum value" + @JS static let enumConstant: Int = 42 + @JS nonisolated(unsafe) static var enumBool: Bool = false + + @JS nonisolated(unsafe) static var enumVariable: Int = 200 + + @JS static var computedReadonly: Int { + return enumVariable * 2 + } + + @JS static var computedReadWrite: String { + get { + return "Value: \(enumVariable)" + } + set { + if let range = newValue.range(of: "Value: "), + let number = Int(String(newValue[range.upperBound...])) + { + enumVariable = number + } + } + } +} + +@JS enum StaticPropertyNamespace { + @JS nonisolated(unsafe) static var namespaceProperty: String = "namespace" + @JS static let namespaceConstant: String = "constant" + + @JS enum NestedProperties { + @JS nonisolated(unsafe) static var nestedProperty: Int = 999 + @JS static let nestedConstant: String = "nested" + @JS nonisolated(unsafe) static var nestedDouble: Double = 1.414 + } +} + +// MARK: - Protocol Tests + +@JS protocol DataProcessor { + var count: Int { get set } + var name: String { get } + var optionalTag: String? { get set } + var optionalCount: Int? { get set } + var direction: Direction? { get set } + var optionalTheme: Theme? { get set } + var httpStatus: HttpStatus? { get set } + var apiResult: APIResult? { get set } + var helper: Greeter { get set } + var optionalHelper: Greeter? { get set } + func increment(by amount: Int) + func getValue() -> Int + func setLabelElements(_ labelPrefix: String, _ labelSuffix: String) + func getLabel() -> String + func isEven() -> Bool + func processGreeter(_ greeter: Greeter) -> String + func createGreeter() -> Greeter + func processOptionalGreeter(_ greeter: Greeter?) -> String + func createOptionalGreeter() -> Greeter? + func handleAPIResult(_ result: APIResult?) + func getAPIResult() -> APIResult? +} + +@JS class DataProcessorManager { + + @JS var processor: DataProcessor + @JS var backupProcessor: DataProcessor? + + @JS init(processor: DataProcessor) { + self.processor = processor + self.backupProcessor = nil + } + + @JS func incrementByAmount(_ amount: Int) { + processor.increment(by: amount) + } + + @JS func setProcessorLabel(_ prefix: String, _ suffix: String) { + processor.setLabelElements(prefix, suffix) + } + + @JS func isProcessorEven() -> Bool { + return processor.isEven() + } + + @JS func getProcessorLabel() -> String { + return processor.getLabel() + } + + @JS func getCurrentValue() -> Int { + return processor.getValue() + } + + @JS func incrementBoth() { + processor.increment(by: 1) + backupProcessor?.increment(by: 1) + } + + @JS func getBackupValue() -> Int? { + return backupProcessor?.getValue() + } + + @JS func hasBackup() -> Bool { + return backupProcessor != nil + } + + @JS func getProcessorOptionalTag() -> String? { + return processor.optionalTag + } + + @JS func setProcessorOptionalTag(_ tag: String?) { + processor.optionalTag = tag + } + + @JS func getProcessorOptionalCount() -> Int? { + return processor.optionalCount + } + + @JS func setProcessorOptionalCount(_ count: Int?) { + processor.optionalCount = count + } + + @JS func getProcessorDirection() -> Direction? { + return processor.direction + } + + @JS func setProcessorDirection(_ direction: Direction?) { + processor.direction = direction + } + + @JS func getProcessorTheme() -> Theme? { + return processor.optionalTheme + } + + @JS func setProcessorTheme(_ theme: Theme?) { + processor.optionalTheme = theme + } + + @JS func getProcessorHttpStatus() -> HttpStatus? { + return processor.httpStatus + } + + @JS func setProcessorHttpStatus(_ status: HttpStatus?) { + processor.httpStatus = status + } + + @JS func getProcessorAPIResult() -> APIResult? { + return processor.getAPIResult() + } + + @JS func setProcessorAPIResult(_ apiResult: APIResult?) { + processor.handleAPIResult(apiResult) + } +} + +@JS class SwiftDataProcessor: DataProcessor { + @JS var count: Int = 0 + @JS let name: String = "SwiftDataProcessor" + @JS var optionalTag: String? = nil + @JS var optionalCount: Int? = nil + @JS var direction: Direction? = nil + @JS var optionalTheme: Theme? = nil + @JS var httpStatus: HttpStatus? = nil + @JS var apiResult: APIResult? = nil + @JS var helper: Greeter = Greeter(name: "DefaultHelper") + @JS var optionalHelper: Greeter? = nil + private var label: String = "" + + @JS init() {} + + @JS func increment(by amount: Int) { + count += amount + } + + @JS func getValue() -> Int { + return count + } + + @JS func setLabelElements(_ labelPrefix: String, _ labelSuffix: String) { + self.label = labelPrefix + labelSuffix + } + + @JS func getLabel() -> String { + return label + } + + @JS func isEven() -> Bool { + return count % 2 == 0 + } + + @JS func processGreeter(_ greeter: Greeter) -> String { + return "SwiftProcessor processed: \(greeter.greet())" + } + + @JS func createGreeter() -> Greeter { + return Greeter(name: "ProcessorGreeter") + } + + @JS func processOptionalGreeter(_ greeter: Greeter?) -> String { + if let greeter = greeter { + return "SwiftProcessor processed optional: \(greeter.greet())" + } else { + return "SwiftProcessor received nil" + } + } + + @JS func createOptionalGreeter() -> Greeter? { + return Greeter(name: "OptionalProcessorGreeter") + } + + @JS func handleAPIResult(_ result: APIResult?) { + self.apiResult = result + } + + @JS func getAPIResult() -> APIResult? { + return apiResult + } +} + +// MARK: - Closure Tests + +// @JS func makeFormatter(prefix: String) -> (String) -> String { +// return { value in "\(prefix) \(value)" } +// } + +@JS func formatName(_ name: String, transform: (String) -> String) -> String { + return transform(name) +} + +@JS func makeFormatter(prefix: String) -> (String) -> String { + return { value in "\(prefix) \(value)" } +} + +@JS func makeAdder(base: Int) -> (Int) -> Int { + return { value in base + value } +} + +@JS class TextProcessor { + private var transform: (String) -> String + + @JS init(transform: @escaping (String) -> String) { + self.transform = transform + } + + @JS func process(_ text: String) -> String { + return transform(text) + } + + @JS func processWithCustom(_ text: String, customTransform: (Int, String, Double) -> String) -> String { + return customTransform(42, text, 3.14) + } + + @JS func getTransform() -> (String) -> String { + return transform + } + + @JS func processOptionalString(_ callback: (String?) -> String) -> String { + return callback("test") + " | " + callback(nil) + } + + @JS func processOptionalInt(_ callback: (Int?) -> String) -> String { + return callback(42) + " | " + callback(nil) + } + + @JS func processOptionalGreeter(_ callback: (Greeter?) -> String) -> String { + let greeter = Greeter(name: "Alice") + return callback(greeter) + " | " + callback(nil) + } + + @JS func makeOptionalStringFormatter() -> (String?) -> String { + return { value in + if let value = value { + return "Got: \(value)" + } else { + return "Got: nil" + } + } + } + + @JS func makeOptionalGreeterCreator() -> () -> Greeter? { + var count = 0 + return { + count += 1 + if count % 2 == 0 { + return Greeter(name: "Greeter\(count)") + } else { + return nil + } + } + } + + @JS func processDirection(_ callback: (Direction) -> String) -> String { + return callback(.north) + } + + @JS func processTheme(_ callback: (Theme) -> String) -> String { + return callback(.dark) + } + + @JS func processHttpStatus(_ callback: (HttpStatus) -> Int) -> Int { + return callback(.ok) + } + + @JS func processAPIResult(_ callback: (APIResult) -> String) -> String { + return callback(.success("test")) + } + + @JS func makeDirectionChecker() -> (Direction) -> Bool { + return { direction in + direction == .north || direction == .south + } + } + + @JS func makeThemeValidator() -> (Theme) -> Bool { + return { theme in + theme == .dark + } + } + + @JS func makeStatusCodeExtractor() -> (HttpStatus) -> Int { + return { status in + switch status { + case .ok: return 200 + case .notFound: return 404 + case .serverError: return 500 + case .unknown: return -1 + } + } + } + + @JS func makeAPIResultHandler() -> (APIResult) -> String { + return { result in + switch result { + case .success(let message): return "Success: \(message)" + case .failure(let code): return "Failure: \(code)" + case .info: return "Info" + case .flag(let value): return "Flag: \(value)" + case .rate(let value): return "Rate: \(value)" + case .precise(let value): return "Precise: \(value)" + } + } + } + + @JS func processOptionalDirection(_ callback: (Direction?) -> String) -> String { + return callback(.north) + " | " + callback(nil) + } + + @JS func processOptionalTheme(_ callback: (Theme?) -> String) -> String { + return callback(.light) + " | " + callback(nil) + } + + @JS func processOptionalAPIResult(_ callback: (APIResult?) -> String) -> String { + return callback(.success("ok")) + " | " + callback(nil) + } + + @JS func makeOptionalDirectionFormatter() -> (Direction?) -> String { + return { direction in + if let direction = direction { + switch direction { + case .north: return "N" + case .south: return "S" + case .east: return "E" + case .west: return "W" + } + } else { + return "nil" + } + } + } +} + +// MARK: - Array Tests + +// Primitive arrays +@JS func roundTripIntArray(_ values: [Int]) -> [Int] { + return values +} + +@JS func roundTripStringArray(_ values: [String]) -> [String] { + return values +} + +@JS func roundTripDoubleArray(_ values: [Double]) -> [Double] { + return values +} + +@JS func roundTripBoolArray(_ values: [Bool]) -> [Bool] { + return values +} + +// Enum arrays +@JS func roundTripDirectionArray(_ values: [Direction]) -> [Direction] { + return values +} + +@JS func roundTripStatusArray(_ values: [Status]) -> [Status] { + return values +} + +@JS func roundTripThemeArray(_ values: [Theme]) -> [Theme] { + return values +} + +@JS func roundTripHttpStatusArray(_ values: [HttpStatus]) -> [HttpStatus] { + return values +} + +// Struct arrays +@JS func roundTripDataPointArray(_ points: [DataPoint]) -> [DataPoint] { + return points +} + +// Class arrays +@JS func roundTripGreeterArray(_ greeters: [Greeter]) -> [Greeter] { + return greeters +} + +// Arrays of optional elements +@JS func roundTripOptionalIntArray(_ values: [Int?]) -> [Int?] { + return values +} + +@JS func roundTripOptionalStringArray(_ values: [String?]) -> [String?] { + return values +} + +@JS func roundTripOptionalDataPointArray(_ points: [DataPoint?]) -> [DataPoint?] { + return points +} + +@JS func roundTripOptionalDirectionArray(_ directions: [Direction?]) -> [Direction?] { + return directions +} + +@JS func roundTripOptionalStatusArray(_ statuses: [Status?]) -> [Status?] { + return statuses +} + +// Optional arrays +@JS func roundTripOptionalIntArrayType(_ values: [Int]?) -> [Int]? { + return values +} + +@JS func roundTripOptionalStringArrayType(_ values: [String]?) -> [String]? { + return values +} + +@JS func roundTripOptionalGreeterArrayType(_ greeters: [Greeter]?) -> [Greeter]? { + return greeters +} + +// Nested arrays + +@JS func roundTripNestedIntArray(_ values: [[Int]]) -> [[Int]] { + return values +} + +@JS func roundTripNestedStringArray(_ values: [[String]]) -> [[String]] { + return values +} + +@JS func roundTripNestedDoubleArray(_ values: [[Double]]) -> [[Double]] { + return values +} + +@JS func roundTripNestedBoolArray(_ values: [[Bool]]) -> [[Bool]] { + return values +} + +@JS func roundTripNestedDataPointArray(_ points: [[DataPoint]]) -> [[DataPoint]] { + return points +} + +@JS func roundTripNestedDirectionArray(_ directions: [[Direction]]) -> [[Direction]] { + return directions +} + +@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 roundTripUnsafePointerArray(_ values: [UnsafePointer]) -> [UnsafePointer] { + return values +} +@JS func roundTripUnsafeMutablePointerArray(_ values: [UnsafeMutablePointer]) -> [UnsafeMutablePointer] { + return values +} + +@JS func consumeDataProcessorArrayType(_ processors: [DataProcessor]) -> Int { + return processors.count +} + +@JS func roundTripDataProcessorArrayType(_ processors: [DataProcessor]) -> [DataProcessor] { + return processors +} + +@JS func roundTripJSObjectArray(_ objects: [JSObject]) -> [JSObject] { + return objects +} + +@JS func roundTripOptionalJSObjectArray(_ objects: [JSObject?]) -> [JSObject?] { + return objects +} + +@JS func roundTripFooArray(_ foos: [Foo]) -> [Foo] { + return foos +} + +@JS func roundTripOptionalFooArray(_ foos: [Foo?]) -> [Foo?] { + return foos +} + class ExportAPITests: XCTestCase { func testAll() { var hasDeinitGreeter = false diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift deleted file mode 100644 index 579dd36b8..000000000 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift +++ /dev/null @@ -1,570 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -@_expose(wasm, "bjs_roundTripVoid") -@_cdecl("bjs_roundTripVoid") -public func _bjs_roundTripVoid() -> Void { - #if arch(wasm32) - roundTripVoid() - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_roundTripInt") -@_cdecl("bjs_roundTripInt") -public func _bjs_roundTripInt(v: Int32) -> Int32 { - #if arch(wasm32) - let ret = roundTripInt(v: Int(v)) - return Int32(ret) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_roundTripFloat") -@_cdecl("bjs_roundTripFloat") -public func _bjs_roundTripFloat(v: Float32) -> Float32 { - #if arch(wasm32) - let ret = roundTripFloat(v: v) - return Float32(ret) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_roundTripDouble") -@_cdecl("bjs_roundTripDouble") -public func _bjs_roundTripDouble(v: Float64) -> Float64 { - #if arch(wasm32) - let ret = roundTripDouble(v: v) - return Float64(ret) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_roundTripBool") -@_cdecl("bjs_roundTripBool") -public func _bjs_roundTripBool(v: Int32) -> Int32 { - #if arch(wasm32) - let ret = roundTripBool(v: v == 1) - return Int32(ret ? 1 : 0) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_roundTripString") -@_cdecl("bjs_roundTripString") -public func _bjs_roundTripString(vBytes: Int32, vLen: Int32) -> Void { - #if arch(wasm32) - let v = String(unsafeUninitializedCapacity: Int(vLen)) { b in - _swift_js_init_memory(vBytes, b.baseAddress.unsafelyUnwrapped) - return Int(vLen) - } - var ret = roundTripString(v: v) - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_roundTripSwiftHeapObject") -@_cdecl("bjs_roundTripSwiftHeapObject") -public func _bjs_roundTripSwiftHeapObject(v: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { - #if arch(wasm32) - let ret = roundTripSwiftHeapObject(v: Unmanaged.fromOpaque(v).takeUnretainedValue()) - return Unmanaged.passRetained(ret).toOpaque() - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_roundTripJSObject") -@_cdecl("bjs_roundTripJSObject") -public func _bjs_roundTripJSObject(v: Int32) -> Int32 { - #if arch(wasm32) - let ret = roundTripJSObject(v: JSObject(id: UInt32(bitPattern: v))) - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_throwsSwiftError") -@_cdecl("bjs_throwsSwiftError") -public func _bjs_throwsSwiftError(shouldThrow: Int32) -> Void { - #if arch(wasm32) - do { - try throwsSwiftError(shouldThrow: shouldThrow == 1) - } catch let error { - if let error = error.thrownValue.object { - withExtendedLifetime(error) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } else { - let jsError = JSError(message: String(describing: error)) - withExtendedLifetime(jsError.jsObject) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } - return - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_throwsWithIntResult") -@_cdecl("bjs_throwsWithIntResult") -public func _bjs_throwsWithIntResult() -> Int32 { - #if arch(wasm32) - do { - let ret = try throwsWithIntResult() - return Int32(ret) - } catch let error { - if let error = error.thrownValue.object { - withExtendedLifetime(error) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } else { - let jsError = JSError(message: String(describing: error)) - withExtendedLifetime(jsError.jsObject) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } - return 0 - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_throwsWithStringResult") -@_cdecl("bjs_throwsWithStringResult") -public func _bjs_throwsWithStringResult() -> Void { - #if arch(wasm32) - do { - var ret = try throwsWithStringResult() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - } catch let error { - if let error = error.thrownValue.object { - withExtendedLifetime(error) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } else { - let jsError = JSError(message: String(describing: error)) - withExtendedLifetime(jsError.jsObject) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } - return - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_throwsWithBoolResult") -@_cdecl("bjs_throwsWithBoolResult") -public func _bjs_throwsWithBoolResult() -> Int32 { - #if arch(wasm32) - do { - let ret = try throwsWithBoolResult() - return Int32(ret ? 1 : 0) - } catch let error { - if let error = error.thrownValue.object { - withExtendedLifetime(error) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } else { - let jsError = JSError(message: String(describing: error)) - withExtendedLifetime(jsError.jsObject) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } - return 0 - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_throwsWithFloatResult") -@_cdecl("bjs_throwsWithFloatResult") -public func _bjs_throwsWithFloatResult() -> Float32 { - #if arch(wasm32) - do { - let ret = try throwsWithFloatResult() - return Float32(ret) - } catch let error { - if let error = error.thrownValue.object { - withExtendedLifetime(error) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } else { - let jsError = JSError(message: String(describing: error)) - withExtendedLifetime(jsError.jsObject) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } - return 0.0 - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_throwsWithDoubleResult") -@_cdecl("bjs_throwsWithDoubleResult") -public func _bjs_throwsWithDoubleResult() -> Float64 { - #if arch(wasm32) - do { - let ret = try throwsWithDoubleResult() - return Float64(ret) - } catch let error { - if let error = error.thrownValue.object { - withExtendedLifetime(error) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } else { - let jsError = JSError(message: String(describing: error)) - withExtendedLifetime(jsError.jsObject) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } - return 0.0 - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_throwsWithSwiftHeapObjectResult") -@_cdecl("bjs_throwsWithSwiftHeapObjectResult") -public func _bjs_throwsWithSwiftHeapObjectResult() -> UnsafeMutableRawPointer { - #if arch(wasm32) - do { - let ret = try throwsWithSwiftHeapObjectResult() - return Unmanaged.passRetained(ret).toOpaque() - } catch let error { - if let error = error.thrownValue.object { - withExtendedLifetime(error) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } else { - let jsError = JSError(message: String(describing: error)) - withExtendedLifetime(jsError.jsObject) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } - return UnsafeMutableRawPointer(bitPattern: -1).unsafelyUnwrapped - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_throwsWithJSObjectResult") -@_cdecl("bjs_throwsWithJSObjectResult") -public func _bjs_throwsWithJSObjectResult() -> Int32 { - #if arch(wasm32) - do { - let ret = try throwsWithJSObjectResult() - return _swift_js_retain(Int32(bitPattern: ret.id)) - } catch let error { - if let error = error.thrownValue.object { - withExtendedLifetime(error) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } else { - let jsError = JSError(message: String(describing: error)) - withExtendedLifetime(jsError.jsObject) { - _swift_js_throw(Int32(bitPattern: $0.id)) - } - } - return 0 - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_asyncRoundTripVoid") -@_cdecl("bjs_asyncRoundTripVoid") -public func _bjs_asyncRoundTripVoid() -> Int32 { - #if arch(wasm32) - let ret = JSPromise.async { - await asyncRoundTripVoid() - } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_asyncRoundTripInt") -@_cdecl("bjs_asyncRoundTripInt") -public func _bjs_asyncRoundTripInt(v: Int32) -> Int32 { - #if arch(wasm32) - let ret = JSPromise.async { - return await asyncRoundTripInt(v: Int(v)).jsValue - } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_asyncRoundTripFloat") -@_cdecl("bjs_asyncRoundTripFloat") -public func _bjs_asyncRoundTripFloat(v: Float32) -> Int32 { - #if arch(wasm32) - let ret = JSPromise.async { - return await asyncRoundTripFloat(v: v).jsValue - } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_asyncRoundTripDouble") -@_cdecl("bjs_asyncRoundTripDouble") -public func _bjs_asyncRoundTripDouble(v: Float64) -> Int32 { - #if arch(wasm32) - let ret = JSPromise.async { - return await asyncRoundTripDouble(v: v).jsValue - } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_asyncRoundTripBool") -@_cdecl("bjs_asyncRoundTripBool") -public func _bjs_asyncRoundTripBool(v: Int32) -> Int32 { - #if arch(wasm32) - let ret = JSPromise.async { - return await asyncRoundTripBool(v: v == 1).jsValue - } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_asyncRoundTripString") -@_cdecl("bjs_asyncRoundTripString") -public func _bjs_asyncRoundTripString(vBytes: Int32, vLen: Int32) -> Int32 { - #if arch(wasm32) - let ret = JSPromise.async { - let v = String(unsafeUninitializedCapacity: Int(vLen)) { b in - _swift_js_init_memory(vBytes, b.baseAddress.unsafelyUnwrapped) - return Int(vLen) - } - return await asyncRoundTripString(v: v).jsValue - } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_asyncRoundTripSwiftHeapObject") -@_cdecl("bjs_asyncRoundTripSwiftHeapObject") -public func _bjs_asyncRoundTripSwiftHeapObject(v: UnsafeMutableRawPointer) -> Int32 { - #if arch(wasm32) - let ret = JSPromise.async { - return await asyncRoundTripSwiftHeapObject(v: Unmanaged.fromOpaque(v).takeUnretainedValue()).jsValue - } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_asyncRoundTripJSObject") -@_cdecl("bjs_asyncRoundTripJSObject") -public func _bjs_asyncRoundTripJSObject(v: Int32) -> Int32 { - #if arch(wasm32) - let ret = JSPromise.async { - return await asyncRoundTripJSObject(v: JSObject(id: UInt32(bitPattern: v))).jsValue - } .jsObject - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_takeGreeter") -@_cdecl("bjs_takeGreeter") -public func _bjs_takeGreeter(g: UnsafeMutableRawPointer, nameBytes: Int32, nameLen: Int32) -> Void { - #if arch(wasm32) - let name = String(unsafeUninitializedCapacity: Int(nameLen)) { b in - _swift_js_init_memory(nameBytes, b.baseAddress.unsafelyUnwrapped) - return Int(nameLen) - } - takeGreeter(g: Unmanaged.fromOpaque(g).takeUnretainedValue(), name: name) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_createCalculator") -@_cdecl("bjs_createCalculator") -public func _bjs_createCalculator() -> UnsafeMutableRawPointer { - #if arch(wasm32) - let ret = createCalculator() - return Unmanaged.passRetained(ret).toOpaque() - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_useCalculator") -@_cdecl("bjs_useCalculator") -public func _bjs_useCalculator(calc: UnsafeMutableRawPointer, x: Int32, y: Int32) -> Int32 { - #if arch(wasm32) - let ret = useCalculator(calc: Unmanaged.fromOpaque(calc).takeUnretainedValue(), x: Int(x), y: Int(y)) - return Int32(ret) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_testGreeterToJSValue") -@_cdecl("bjs_testGreeterToJSValue") -public func _bjs_testGreeterToJSValue() -> Int32 { - #if arch(wasm32) - let ret = testGreeterToJSValue() - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_testCalculatorToJSValue") -@_cdecl("bjs_testCalculatorToJSValue") -public func _bjs_testCalculatorToJSValue() -> Int32 { - #if arch(wasm32) - let ret = testCalculatorToJSValue() - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_testSwiftClassAsJSValue") -@_cdecl("bjs_testSwiftClassAsJSValue") -public func _bjs_testSwiftClassAsJSValue(greeter: UnsafeMutableRawPointer) -> Int32 { - #if arch(wasm32) - let ret = testSwiftClassAsJSValue(greeter: Unmanaged.fromOpaque(greeter).takeUnretainedValue()) - return _swift_js_retain(Int32(bitPattern: ret.id)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_Greeter_init") -@_cdecl("bjs_Greeter_init") -public func _bjs_Greeter_init(nameBytes: Int32, nameLen: Int32) -> UnsafeMutableRawPointer { - #if arch(wasm32) - let name = String(unsafeUninitializedCapacity: Int(nameLen)) { b in - _swift_js_init_memory(nameBytes, b.baseAddress.unsafelyUnwrapped) - return Int(nameLen) - } - let ret = Greeter(name: name) - return Unmanaged.passRetained(ret).toOpaque() - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_Greeter_greet") -@_cdecl("bjs_Greeter_greet") -public func _bjs_Greeter_greet(_self: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - var ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().greet() - return ret.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - } - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_Greeter_changeName") -@_cdecl("bjs_Greeter_changeName") -public func _bjs_Greeter_changeName(_self: UnsafeMutableRawPointer, nameBytes: Int32, nameLen: Int32) -> Void { - #if arch(wasm32) - let name = String(unsafeUninitializedCapacity: Int(nameLen)) { b in - _swift_js_init_memory(nameBytes, b.baseAddress.unsafelyUnwrapped) - return Int(nameLen) - } - Unmanaged.fromOpaque(_self).takeUnretainedValue().changeName(name: name) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_Greeter_deinit") -@_cdecl("bjs_Greeter_deinit") -public func _bjs_Greeter_deinit(pointer: UnsafeMutableRawPointer) { - Unmanaged.fromOpaque(pointer).release() -} - -extension Greeter: ConvertibleToJSValue { - var jsValue: JSValue { - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Greeter_wrap") - func _bjs_Greeter_wrap(_: UnsafeMutableRawPointer) -> Int32 - return .object(JSObject(id: UInt32(bitPattern: _bjs_Greeter_wrap(Unmanaged.passRetained(self).toOpaque())))) - } -} - -@_expose(wasm, "bjs_Calculator_square") -@_cdecl("bjs_Calculator_square") -public func _bjs_Calculator_square(_self: UnsafeMutableRawPointer, value: Int32) -> Int32 { - #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().square(value: Int(value)) - return Int32(ret) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_Calculator_add") -@_cdecl("bjs_Calculator_add") -public func _bjs_Calculator_add(_self: UnsafeMutableRawPointer, a: Int32, b: Int32) -> Int32 { - #if arch(wasm32) - let ret = Unmanaged.fromOpaque(_self).takeUnretainedValue().add(a: Int(a), b: Int(b)) - return Int32(ret) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_Calculator_deinit") -@_cdecl("bjs_Calculator_deinit") -public func _bjs_Calculator_deinit(pointer: UnsafeMutableRawPointer) { - Unmanaged.fromOpaque(pointer).release() -} - -extension Calculator: ConvertibleToJSValue { - var jsValue: JSValue { - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Calculator_wrap") - func _bjs_Calculator_wrap(_: UnsafeMutableRawPointer) -> Int32 - return .object(JSObject(id: UInt32(bitPattern: _bjs_Calculator_wrap(Unmanaged.passRetained(self).toOpaque())))) - } -} \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ImportTS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ImportTS.swift deleted file mode 100644 index 255853fa0..000000000 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ImportTS.swift +++ /dev/null @@ -1,295 +0,0 @@ -// 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(BridgeJS) import JavaScriptKit - -func jsRoundTripVoid() throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripVoid") - func bjs_jsRoundTripVoid() -> Void - #else - func bjs_jsRoundTripVoid() -> Void { - fatalError("Only available on WebAssembly") - } - #endif - bjs_jsRoundTripVoid() - if let error = _swift_js_take_exception() { - throw error - } -} - -func jsRoundTripNumber(_ v: Double) throws(JSException) -> Double { - #if arch(wasm32) - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripNumber") - func bjs_jsRoundTripNumber(_ v: Float64) -> Float64 - #else - func bjs_jsRoundTripNumber(_ v: Float64) -> Float64 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_jsRoundTripNumber(v) - if let error = _swift_js_take_exception() { - throw error - } - return Double(ret) -} - -func jsRoundTripBool(_ v: Bool) throws(JSException) -> Bool { - #if arch(wasm32) - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripBool") - func bjs_jsRoundTripBool(_ v: Int32) -> Int32 - #else - func bjs_jsRoundTripBool(_ v: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_jsRoundTripBool(Int32(v ? 1 : 0)) - if let error = _swift_js_take_exception() { - throw error - } - return ret == 1 -} - -func jsRoundTripString(_ v: String) throws(JSException) -> String { - #if arch(wasm32) - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripString") - func bjs_jsRoundTripString(_ v: Int32) -> Int32 - #else - func bjs_jsRoundTripString(_ v: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - var v = v - let vId = v.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_jsRoundTripString(vId) - if let error = _swift_js_take_exception() { - throw error - } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } -} - -func jsThrowOrVoid(_ shouldThrow: Bool) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsThrowOrVoid") - func bjs_jsThrowOrVoid(_ shouldThrow: Int32) -> Void - #else - func bjs_jsThrowOrVoid(_ shouldThrow: Int32) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - bjs_jsThrowOrVoid(Int32(shouldThrow ? 1 : 0)) - if let error = _swift_js_take_exception() { - throw error - } -} - -func jsThrowOrNumber(_ shouldThrow: Bool) throws(JSException) -> Double { - #if arch(wasm32) - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsThrowOrNumber") - func bjs_jsThrowOrNumber(_ shouldThrow: Int32) -> Float64 - #else - func bjs_jsThrowOrNumber(_ shouldThrow: Int32) -> Float64 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_jsThrowOrNumber(Int32(shouldThrow ? 1 : 0)) - if let error = _swift_js_take_exception() { - throw error - } - return Double(ret) -} - -func jsThrowOrBool(_ shouldThrow: Bool) throws(JSException) -> Bool { - #if arch(wasm32) - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsThrowOrBool") - func bjs_jsThrowOrBool(_ shouldThrow: Int32) -> Int32 - #else - func bjs_jsThrowOrBool(_ shouldThrow: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_jsThrowOrBool(Int32(shouldThrow ? 1 : 0)) - if let error = _swift_js_take_exception() { - throw error - } - return ret == 1 -} - -func jsThrowOrString(_ shouldThrow: Bool) throws(JSException) -> String { - #if arch(wasm32) - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsThrowOrString") - func bjs_jsThrowOrString(_ shouldThrow: Int32) -> Int32 - #else - func bjs_jsThrowOrString(_ shouldThrow: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_jsThrowOrString(Int32(shouldThrow ? 1 : 0)) - if let error = _swift_js_take_exception() { - throw error - } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } -} - -func runAsyncWorks() throws(JSException) -> JSPromise { - #if arch(wasm32) - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_runAsyncWorks") - func bjs_runAsyncWorks() -> Int32 - #else - func bjs_runAsyncWorks() -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_runAsyncWorks() - if let error = _swift_js_take_exception() { - throw error - } - return JSPromise(takingThis: ret) -} - -struct JsGreeter { - let this: JSObject - - init(this: JSObject) { - self.this = this - } - - init(takingThis this: Int32) { - self.this = JSObject(id: UInt32(bitPattern: this)) - } - - init(_ name: String, _ prefix: String) throws(JSException) { - #if arch(wasm32) - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JsGreeter_init") - func bjs_JsGreeter_init(_ name: Int32, _ prefix: Int32) -> Int32 - #else - func bjs_JsGreeter_init(_ name: Int32, _ prefix: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - var name = name - let nameId = name.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - var prefix = prefix - let prefixId = prefix.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - let ret = bjs_JsGreeter_init(nameId, prefixId) - if let error = _swift_js_take_exception() { - throw error - } - self.this = JSObject(id: UInt32(bitPattern: ret)) - } - - var name: String { - get throws(JSException) { - #if arch(wasm32) - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JsGreeter_name_get") - func bjs_JsGreeter_name_get(_ self: Int32) -> Int32 - #else - func bjs_JsGreeter_name_get(_ self: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_JsGreeter_name_get(Int32(bitPattern: self.this.id)) - if let error = _swift_js_take_exception() { - throw error - } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } - } - } - - func setName(_ newValue: String) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JsGreeter_name_set") - func bjs_JsGreeter_name_set(_ self: Int32, _ newValue: Int32) -> Void - #else - func bjs_JsGreeter_name_set(_ self: Int32, _ newValue: Int32) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - var newValue = newValue - let newValueId = newValue.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_JsGreeter_name_set(Int32(bitPattern: self.this.id), newValueId) - if let error = _swift_js_take_exception() { - throw error - } - } - - var prefix: String { - get throws(JSException) { - #if arch(wasm32) - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JsGreeter_prefix_get") - func bjs_JsGreeter_prefix_get(_ self: Int32) -> Int32 - #else - func bjs_JsGreeter_prefix_get(_ self: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_JsGreeter_prefix_get(Int32(bitPattern: self.this.id)) - if let error = _swift_js_take_exception() { - throw error - } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } - } - } - - func greet() throws(JSException) -> String { - #if arch(wasm32) - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JsGreeter_greet") - func bjs_JsGreeter_greet(_ self: Int32) -> Int32 - #else - func bjs_JsGreeter_greet(_ self: Int32) -> Int32 { - fatalError("Only available on WebAssembly") - } - #endif - let ret = bjs_JsGreeter_greet(Int32(bitPattern: self.this.id)) - if let error = _swift_js_take_exception() { - throw error - } - return String(unsafeUninitializedCapacity: Int(ret)) { b in - _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(ret)) - return Int(ret) - } - } - - func changeName(_ name: String) throws(JSException) -> Void { - #if arch(wasm32) - @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JsGreeter_changeName") - func bjs_JsGreeter_changeName(_ self: Int32, _ name: Int32) -> Void - #else - func bjs_JsGreeter_changeName(_ self: Int32, _ name: Int32) -> Void { - fatalError("Only available on WebAssembly") - } - #endif - var name = name - let nameId = name.withUTF8 { b in - _swift_js_make_js_string(b.baseAddress.unsafelyUnwrapped, Int32(b.count)) - } - bjs_JsGreeter_changeName(Int32(bitPattern: self.this.id), nameId) - if let error = _swift_js_take_exception() { - throw error - } - } - -} \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.Macros.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.Macros.swift new file mode 100644 index 000000000..c63a421e0 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.Macros.swift @@ -0,0 +1,90 @@ +// 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(BridgeJS) import JavaScriptKit + +@JSFunction func jsRoundTripVoid() throws(JSException) -> Void + +@JSFunction func jsRoundTripNumber(_ v: Double) throws(JSException) -> Double + +@JSFunction func jsRoundTripBool(_ v: Bool) throws(JSException) -> Bool + +@JSFunction func jsRoundTripString(_ v: String) throws(JSException) -> String + +@JSFunction func jsRoundTripJSValue(_ v: JSValue) throws(JSException) -> JSValue + +@JSFunction func jsRoundTripJSValueArray(_ v: [JSValue]) throws(JSException) -> [JSValue] + +@JSFunction func jsRoundTripOptionalJSValueArray(_ v: Optional<[JSValue]>) throws(JSException) -> Optional<[JSValue]> + +@JSFunction func jsThrowOrVoid(_ shouldThrow: Bool) throws(JSException) -> Void + +@JSFunction func jsThrowOrNumber(_ shouldThrow: Bool) throws(JSException) -> Double + +@JSFunction func jsThrowOrBool(_ shouldThrow: Bool) throws(JSException) -> Bool + +@JSFunction func jsThrowOrString(_ shouldThrow: Bool) throws(JSException) -> String + +enum FeatureFlag: String { + case foo = "foo" + case bar = "bar" +} +extension FeatureFlag: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum {} + +@JSFunction func jsRoundTripFeatureFlag(_ flag: FeatureFlag) throws(JSException) -> FeatureFlag + +@JSClass struct JsGreeter { + @JSGetter var name: String + @JSSetter func setName(_ value: String) throws(JSException) + @JSGetter var `prefix`: String + @JSFunction init(_ name: String, _ `prefix`: String) throws(JSException) + @JSFunction func greet() throws(JSException) -> String + @JSFunction func changeName(_ name: String) throws(JSException) -> Void +} + +@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 +} + +@JSClass struct StaticBox { + @JSFunction init(_ value: Double) throws(JSException) + @JSFunction func value() throws(JSException) -> Double + @JSFunction static func create(_ value: Double) throws(JSException) -> StaticBox + @JSFunction static func value() throws(JSException) -> Double + @JSFunction static func makeDefault() throws(JSException) -> StaticBox + @JSFunction(jsName: "with-dashes") static func with_dashes() throws(JSException) -> StaticBox +} + +@JSFunction func jsRoundTripNumberArray(_ values: [Double]) throws(JSException) -> [Double] + +@JSFunction func jsRoundTripStringArray(_ values: [String]) throws(JSException) -> [String] + +@JSFunction func jsRoundTripBoolArray(_ values: [Bool]) throws(JSException) -> [Bool] + +@JSFunction func jsSumNumberArray(_ values: [Double]) throws(JSException) -> Double + +@JSFunction func jsCreateNumberArray() throws(JSException) -> [Double] + +@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: JSValue diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift new file mode 100644 index 000000000..8c1d63854 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -0,0 +1,10428 @@ +// bridge-js: skip +// 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(BridgeJS) import JavaScriptKit + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTests10HttpStatusO_Si { + static func bridgeJSLift(_ callbackId: Int32) -> (HttpStatus) -> Int { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si(callbackValue, param0Value) + return Int.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (HttpStatus) -> Int { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (HttpStatus) -> Int) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests10HttpStatusO_Si(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(HttpStatus) -> Int>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(HttpStatus.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTests5ThemeO_SS { + static func bridgeJSLift(_ callbackId: Int32) -> (Theme) -> String { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS(callbackValue, param0Value) + return String.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Theme) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Theme) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Theme) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Theme.bridgeJSLiftParameter(param0Bytes, param0Length)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTests5ThemeO_Sb { + static func bridgeJSLift(_ callbackId: Int32) -> (Theme) -> Bool { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb(callbackValue, param0Value) + return Bool.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Theme) -> Bool { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Theme) -> Bool) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Theme) -> Bool>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Theme.bridgeJSLiftParameter(param0Bytes, param0Length)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS(_ callback: Int32, _ param0: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS(_ callback: Int32, _ param0: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTests7GreeterC_SS { + static func bridgeJSLift(_ callbackId: Int32) -> (Greeter) -> String { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Pointer = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS(callbackValue, param0Pointer) + return String.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Greeter) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Greeter) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Greeter) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Greeter.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC { + static func bridgeJSLift(_ callbackId: Int32) -> (JSObject) -> JSObject { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC(callbackValue, param0Value) + return JSObject.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (JSObject) -> JSObject { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (JSObject) -> JSObject) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests8JSObjectC_8JSObjectC(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(JSObject) -> JSObject>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(JSObject.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTests9APIResultO_SS { + static func bridgeJSLift(_ callbackId: Int32) -> (APIResult) -> String { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0CaseId = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS(callbackValue, param0CaseId) + return String.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (APIResult) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (APIResult) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(APIResult) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(APIResult.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTests9DirectionO_SS { + static func bridgeJSLift(_ callbackId: Int32) -> (Direction) -> String { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS(callbackValue, param0Value) + return String.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Direction) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Direction) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Direction) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Direction.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTests9DirectionO_Sb { + static func bridgeJSLift(_ callbackId: Int32) -> (Direction) -> Bool { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb(callbackValue, param0Value) + return Bool.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Direction) -> Bool { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Direction) -> Bool) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests9DirectionO_Sb(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Direction) -> Bool>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Direction.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC(_ callback: Int32, _ param0: Int32) -> UnsafeMutableRawPointer +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC(_ callback: Int32, _ param0: Int32) -> UnsafeMutableRawPointer { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSS_7GreeterC { + static func bridgeJSLift(_ callbackId: Int32) -> (String) -> Greeter { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC(callbackValue, param0Value) + return Greeter.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (String) -> Greeter { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (String) -> Greeter) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(String) -> Greeter>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(String.bridgeJSLiftParameter(param0Bytes, param0Length)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSS_SS { + static func bridgeJSLift(_ callbackId: Int32) -> (String) -> String { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS(callbackValue, param0Value) + return String.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (String) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (String) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(String) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(String.bridgeJSLiftParameter(param0Bytes, param0Length)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd(_ callback: Int32, _ param0: Float64) -> Float64 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd(_ callback: Int32, _ param0: Float64) -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSd_Sd { + static func bridgeJSLift(_ callbackId: Int32) -> (Double) -> Double { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd(callbackValue, param0Value) + return Double.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Double) -> Double { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Double) -> Double) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd(_ boxPtr: UnsafeMutableRawPointer, _ param0: Float64) -> Float64 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Double) -> Double>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Double.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS(_ callback: Int32, _ param0: Int32, _ param1: Int32, _ param2: Float64) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS(_ callback: Int32, _ param0: Int32, _ param1: Int32, _ param2: Float64) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSiSSSd_SS { + static func bridgeJSLift(_ callbackId: Int32) -> (Int, String, Double) -> String { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] (param0, param1, param2) in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let param1Value = param1.bridgeJSLowerParameter() + let param2Value = param2.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS(callbackValue, param0Value, param1Value, param2Value) + return String.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Int, String, Double) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Int, String, Double) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32, _ param1Bytes: Int32, _ param1Length: Int32, _ param2: Float64) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Int, String, Double) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Int.bridgeJSLiftParameter(param0), String.bridgeJSLiftParameter(param1Bytes, param1Length), Double.bridgeJSLiftParameter(param2)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si(_ callback: Int32, _ param0: Int32, _ param1: Int32, _ param2: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si(_ callback: Int32, _ param0: Int32, _ param1: Int32, _ param2: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSiSiSi_Si { + static func bridgeJSLift(_ callbackId: Int32) -> (Int, Int, Int) -> Int { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] (param0, param1, param2) in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let param1Value = param1.bridgeJSLowerParameter() + let param2Value = param2.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si(callbackValue, param0Value, param1Value, param2Value) + return Int.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Int, Int, Int) -> Int { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Int, Int, Int) -> Int) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSiSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32, _ param1: Int32, _ param2: Int32) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Int, Int, Int) -> Int>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Int.bridgeJSLiftParameter(param0), Int.bridgeJSLiftParameter(param1), Int.bridgeJSLiftParameter(param2)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si(_ callback: Int32, _ param0: Int32, _ param1: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si(_ callback: Int32, _ param0: Int32, _ param1: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSiSi_Si { + static func bridgeJSLift(_ callbackId: Int32) -> (Int, Int) -> Int { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] (param0, param1) in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let param1Value = param1.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si(callbackValue, param0Value, param1Value) + return Int.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Int, Int) -> Int { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Int, Int) -> Int) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32, _ param1: Int32) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Int, Int) -> Int>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Int.bridgeJSLiftParameter(param0), Int.bridgeJSLiftParameter(param1)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si(_ callback: Int32, _ param0: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si(_ callback: Int32, _ param0: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSi_Si { + static func bridgeJSLift(_ callbackId: Int32) -> (Int) -> Int { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si(callbackValue, param0Value) + return Int.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Int) -> Int { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Int) -> Int) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_Si(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Int) -> Int>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Int.bridgeJSLiftParameter(param0)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y(_ callback: Int32, _ param0: Int32) -> Void +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y(_ callback: Int32, _ param0: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSi_y { + static func bridgeJSLift(_ callbackId: Int32) -> (Int) -> Void { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y(callbackValue, param0Value) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Int) -> Void { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Int) -> Void) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSi_y(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Int) -> Void>>.fromOpaque(boxPtr).takeUnretainedValue().closure + closure(Int.bridgeJSLiftParameter(param0)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSq5ThemeO_SS { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS(callbackValue, param0IsSome, param0Value) + return String.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Bytes, param0Length)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSq7GreeterC_SS { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Pointer) = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS(callbackValue, param0IsSome, param0Pointer) + return String.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC(_ callback: Int32, _ param0IsSome: Int32, _ param0Pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC(_ callback: Int32, _ param0IsSome: Int32, _ param0Pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Pointer) = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC(callbackValue, param0IsSome, param0Pointer) + return Optional.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> Optional) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSq9APIResultO_SS { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0CaseId) = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS(callbackValue, param0IsSome, param0CaseId) + return String.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9APIResultO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0CaseId)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSq9DirectionO_SS { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS(callbackValue, param0IsSome, param0Value) + return String.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9DirectionO_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSqSS_SS { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS(callbackValue, param0IsSome, param0Value) + return String.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Bytes, param0Length)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Value: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSqSi_SS { + static func bridgeJSLift(_ callbackId: Int32) -> (Optional) -> String { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0Value) = param0.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS(callbackValue, param0IsSome, param0Value) + return String.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Optional) -> String { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Optional) -> String) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSi_SS(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0Value: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> String>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter(param0IsSome, param0Value)) + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb(_ callback: Int32) -> Int32 +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb(_ callback: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsy_Sb { + static func bridgeJSLift(_ callbackId: Int32) -> () -> Bool { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb(callbackValue) + return Bool.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == () -> Bool { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping () -> Bool) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sb(_ boxPtr: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<() -> Bool>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure() + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC(_ callback: Int32) -> UnsafeMutableRawPointer +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC(_ callback: Int32) -> UnsafeMutableRawPointer { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsy_Sq7GreeterC { + static func bridgeJSLift(_ callbackId: Int32) -> () -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC(callbackValue) + return Optional.bridgeJSLiftReturn(ret) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == () -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping () -> Optional) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_Sq7GreeterC(_ boxPtr: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<() -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure() + return result.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y(_ callback: Int32) -> Void +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y(_ callback: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +private enum _BJS_Closure_20BridgeJSRuntimeTestsy_y { + static func bridgeJSLift(_ callbackId: Int32) -> () -> Void { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y(callbackValue) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == () -> Void { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping () -> Void) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsy_y(_ boxPtr: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<() -> Void>>.fromOpaque(boxPtr).takeUnretainedValue().closure + closure() + #else + fatalError("Only available on WebAssembly") + #endif +} + +struct AnyDataProcessor: DataProcessor, _BridgedSwiftProtocolWrapper { + let jsObject: JSObject + + func increment(by amount: Int) -> Void { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let amountValue = amount.bridgeJSLowerParameter() + _extern_increment(jsObjectValue, amountValue) + } + + func getValue() -> Int { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = _extern_getValue(jsObjectValue) + return Int.bridgeJSLiftReturn(ret) + } + + func setLabelElements(_ labelPrefix: String, _ labelSuffix: String) -> Void { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let labelPrefixValue = labelPrefix.bridgeJSLowerParameter() + let labelSuffixValue = labelSuffix.bridgeJSLowerParameter() + _extern_setLabelElements(jsObjectValue, labelPrefixValue, labelSuffixValue) + } + + func getLabel() -> String { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = _extern_getLabel(jsObjectValue) + return String.bridgeJSLiftReturn(ret) + } + + func isEven() -> Bool { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = _extern_isEven(jsObjectValue) + return Bool.bridgeJSLiftReturn(ret) + } + + func processGreeter(_ greeter: Greeter) -> String { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let greeterPointer = greeter.bridgeJSLowerParameter() + let ret = _extern_processGreeter(jsObjectValue, greeterPointer) + return String.bridgeJSLiftReturn(ret) + } + + func createGreeter() -> Greeter { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = _extern_createGreeter(jsObjectValue) + return Greeter.bridgeJSLiftReturn(ret) + } + + func processOptionalGreeter(_ greeter: Optional) -> String { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let (greeterIsSome, greeterPointer) = greeter.bridgeJSLowerParameter() + let ret = _extern_processOptionalGreeter(jsObjectValue, greeterIsSome, greeterPointer) + return String.bridgeJSLiftReturn(ret) + } + + func createOptionalGreeter() -> Optional { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = _extern_createOptionalGreeter(jsObjectValue) + return Optional.bridgeJSLiftReturn(ret) + } + + func handleAPIResult(_ result: Optional) -> Void { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let (resultIsSome, resultCaseId) = result.bridgeJSLowerParameter() + _extern_handleAPIResult(jsObjectValue, resultIsSome, resultCaseId) + } + + func getAPIResult() -> Optional { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = _extern_getAPIResult(jsObjectValue) + return Optional.bridgeJSLiftReturn(ret) + } + + var count: Int { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = bjs_DataProcessor_count_get(jsObjectValue) + return Int.bridgeJSLiftReturn(ret) + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_DataProcessor_count_set(jsObjectValue, newValueValue) + } + } + + var name: String { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = bjs_DataProcessor_name_get(jsObjectValue) + return String.bridgeJSLiftReturn(ret) + } + } + + var optionalTag: Optional { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + bjs_DataProcessor_optionalTag_get(jsObjectValue) + return Optional.bridgeJSLiftReturnFromSideChannel() + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_DataProcessor_optionalTag_set(jsObjectValue, newValueIsSome, newValueValue) + } + } + + var optionalCount: Optional { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + bjs_DataProcessor_optionalCount_get(jsObjectValue) + return Optional.bridgeJSLiftReturnFromSideChannel() + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_DataProcessor_optionalCount_set(jsObjectValue, newValueIsSome, newValueValue) + } + } + + var direction: Optional { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = bjs_DataProcessor_direction_get(jsObjectValue) + return Optional.bridgeJSLiftReturn(ret) + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_DataProcessor_direction_set(jsObjectValue, newValueIsSome, newValueValue) + } + } + + var optionalTheme: Optional { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + bjs_DataProcessor_optionalTheme_get(jsObjectValue) + return Optional.bridgeJSLiftReturnFromSideChannel() + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_DataProcessor_optionalTheme_set(jsObjectValue, newValueIsSome, newValueValue) + } + } + + var httpStatus: Optional { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + bjs_DataProcessor_httpStatus_get(jsObjectValue) + return Optional.bridgeJSLiftReturnFromSideChannel() + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_DataProcessor_httpStatus_set(jsObjectValue, newValueIsSome, newValueValue) + } + } + + var apiResult: Optional { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = bjs_DataProcessor_apiResult_get(jsObjectValue) + return Optional.bridgeJSLiftReturn(ret) + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let (newValueIsSome, newValueCaseId) = newValue.bridgeJSLowerParameter() + bjs_DataProcessor_apiResult_set(jsObjectValue, newValueIsSome, newValueCaseId) + } + } + + var helper: Greeter { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = bjs_DataProcessor_helper_get(jsObjectValue) + return Greeter.bridgeJSLiftReturn(ret) + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let newValuePointer = newValue.bridgeJSLowerParameter() + bjs_DataProcessor_helper_set(jsObjectValue, newValuePointer) + } + } + + var optionalHelper: Optional { + get { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let ret = bjs_DataProcessor_optionalHelper_get(jsObjectValue) + return Optional.bridgeJSLiftReturn(ret) + } + set { + let jsObjectValue = jsObject.bridgeJSLowerParameter() + let (newValueIsSome, newValuePointer) = newValue.bridgeJSLowerParameter() + bjs_DataProcessor_optionalHelper_set(jsObjectValue, newValueIsSome, newValuePointer) + } + } + + static func bridgeJSLiftParameter(_ value: Int32) -> Self { + return AnyDataProcessor(jsObject: JSObject(id: UInt32(bitPattern: value))) + } +} + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_increment") +fileprivate func _extern_increment(_ jsObject: Int32, _ amount: Int32) -> Void + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_getValue") +fileprivate func _extern_getValue(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_setLabelElements") +fileprivate func _extern_setLabelElements(_ jsObject: Int32, _ labelPrefix: Int32, _ labelSuffix: Int32) -> Void + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_getLabel") +fileprivate func _extern_getLabel(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_isEven") +fileprivate func _extern_isEven(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_processGreeter") +fileprivate func _extern_processGreeter(_ jsObject: Int32, _ greeter: UnsafeMutableRawPointer) -> Int32 + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_createGreeter") +fileprivate func _extern_createGreeter(_ jsObject: Int32) -> UnsafeMutableRawPointer + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_processOptionalGreeter") +fileprivate func _extern_processOptionalGreeter(_ jsObject: Int32, _ greeterIsSome: Int32, _ greeterPointer: UnsafeMutableRawPointer) -> Int32 + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_createOptionalGreeter") +fileprivate func _extern_createOptionalGreeter(_ jsObject: Int32) -> UnsafeMutableRawPointer + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_handleAPIResult") +fileprivate func _extern_handleAPIResult(_ jsObject: Int32, _ resultIsSome: Int32, _ resultCaseId: Int32) -> Void + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_getAPIResult") +fileprivate func _extern_getAPIResult(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_count_get") +fileprivate func bjs_DataProcessor_count_get(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_count_set") +fileprivate func bjs_DataProcessor_count_set(_ jsObject: Int32, _ newValue: Int32) -> Void + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_name_get") +fileprivate func bjs_DataProcessor_name_get(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_optionalTag_get") +fileprivate func bjs_DataProcessor_optionalTag_get(_ jsObject: Int32) -> Void + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_optionalTag_set") +fileprivate func bjs_DataProcessor_optionalTag_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_optionalCount_get") +fileprivate func bjs_DataProcessor_optionalCount_get(_ jsObject: Int32) -> Void + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_optionalCount_set") +fileprivate func bjs_DataProcessor_optionalCount_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_direction_get") +fileprivate func bjs_DataProcessor_direction_get(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_direction_set") +fileprivate func bjs_DataProcessor_direction_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_optionalTheme_get") +fileprivate func bjs_DataProcessor_optionalTheme_get(_ jsObject: Int32) -> Void + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_optionalTheme_set") +fileprivate func bjs_DataProcessor_optionalTheme_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_httpStatus_get") +fileprivate func bjs_DataProcessor_httpStatus_get(_ jsObject: Int32) -> Void + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_httpStatus_set") +fileprivate func bjs_DataProcessor_httpStatus_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_apiResult_get") +fileprivate func bjs_DataProcessor_apiResult_get(_ jsObject: Int32) -> Int32 + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_apiResult_set") +fileprivate func bjs_DataProcessor_apiResult_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueCaseId: Int32) -> Void + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_helper_get") +fileprivate func bjs_DataProcessor_helper_get(_ jsObject: Int32) -> UnsafeMutableRawPointer + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_helper_set") +fileprivate func bjs_DataProcessor_helper_set(_ jsObject: Int32, _ newValue: UnsafeMutableRawPointer) -> Void + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_optionalHelper_get") +fileprivate func bjs_DataProcessor_optionalHelper_get(_ jsObject: Int32) -> UnsafeMutableRawPointer + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_optionalHelper_set") +fileprivate func bjs_DataProcessor_optionalHelper_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValuePointer: UnsafeMutableRawPointer) -> Void + +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: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Status { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Status { + return Status(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .loading + case 1: + self = .success + case 2: + self = .error + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .loading: + return 0 + case .success: + return 1 + case .error: + return 2 + } + } +} + +extension Theme: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension HttpStatus: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Precision: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Ratio: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension TSDirection: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> TSDirection { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> TSDirection { + return TSDirection(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 TSTheme: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +@_expose(wasm, "bjs_Utils_StringUtils_static_uppercase") +@_cdecl("bjs_Utils_StringUtils_static_uppercase") +public func _bjs_Utils_StringUtils_static_uppercase(_ textBytes: Int32, _ textLength: Int32) -> Void { + #if arch(wasm32) + let ret = Utils.StringUtils.uppercase(_: String.bridgeJSLiftParameter(textBytes, textLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Utils_StringUtils_static_lowercase") +@_cdecl("bjs_Utils_StringUtils_static_lowercase") +public func _bjs_Utils_StringUtils_static_lowercase(_ textBytes: Int32, _ textLength: Int32) -> Void { + #if arch(wasm32) + let ret = Utils.StringUtils.lowercase(_: String.bridgeJSLiftParameter(textBytes, textLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Networking.API.Method: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Networking.API.Method { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Networking.API.Method { + return Networking.API.Method(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .get + case 1: + self = .post + case 2: + self = .put + case 3: + self = .delete + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .get: + return 0 + case .post: + return 1 + case .put: + return 2 + case .delete: + return 3 + } + } +} + +extension Configuration.LogLevel: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Configuration.Port: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Internal.SupportedMethod: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Internal.SupportedMethod { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Internal.SupportedMethod { + return Internal.SupportedMethod(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .get + case 1: + self = .post + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .get: + return 0 + case .post: + return 1 + } + } +} + +extension APIResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> APIResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(Int.bridgeJSStackPop()) + case 2: + return .flag(Bool.bridgeJSStackPop()) + case 3: + return .rate(Float.bridgeJSStackPop()) + case 4: + return .precise(Double.bridgeJSStackPop()) + case 5: + return .info + default: + fatalError("Unknown APIResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .failure(let param0): + param0.bridgeJSStackPush() + return Int32(1) + case .flag(let param0): + param0.bridgeJSStackPush() + return Int32(2) + case .rate(let param0): + param0.bridgeJSStackPush() + return Int32(3) + case .precise(let param0): + param0.bridgeJSStackPush() + return Int32(4) + case .info: + return Int32(5) + } + } +} + +extension ComplexResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> ComplexResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .error(String.bridgeJSStackPop(), Int.bridgeJSStackPop()) + case 2: + return .location(Double.bridgeJSStackPop(), Double.bridgeJSStackPop(), String.bridgeJSStackPop()) + case 3: + return .status(Bool.bridgeJSStackPop(), Int.bridgeJSStackPop(), String.bridgeJSStackPop()) + case 4: + return .coordinates(Double.bridgeJSStackPop(), Double.bridgeJSStackPop(), Double.bridgeJSStackPop()) + case 5: + return .comprehensive(Bool.bridgeJSStackPop(), Bool.bridgeJSStackPop(), Int.bridgeJSStackPop(), Int.bridgeJSStackPop(), Double.bridgeJSStackPop(), Double.bridgeJSStackPop(), String.bridgeJSStackPop(), String.bridgeJSStackPop(), String.bridgeJSStackPop()) + case 6: + return .info + default: + fatalError("Unknown ComplexResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .error(let param0, let param1): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + return Int32(1) + case .location(let param0, let param1, let param2): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + param2.bridgeJSStackPush() + return Int32(2) + case .status(let param0, let param1, let param2): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + param2.bridgeJSStackPush() + return Int32(3) + case .coordinates(let param0, let param1, let param2): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + param2.bridgeJSStackPush() + return Int32(4) + case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + param2.bridgeJSStackPush() + param3.bridgeJSStackPush() + param4.bridgeJSStackPush() + param5.bridgeJSStackPush() + param6.bridgeJSStackPush() + param7.bridgeJSStackPush() + param8.bridgeJSStackPush() + return Int32(5) + case .info: + return Int32(6) + } + } +} + +extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> Utilities.Result { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(String.bridgeJSStackPop(), Int.bridgeJSStackPop()) + case 2: + return .status(Bool.bridgeJSStackPop(), Int.bridgeJSStackPop(), String.bridgeJSStackPop()) + default: + fatalError("Unknown Utilities.Result case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .failure(let param0, let param1): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + return Int32(1) + case .status(let param0, let param1, let param2): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + param2.bridgeJSStackPush() + return Int32(2) + } + } +} + +extension API.NetworkingResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> API.NetworkingResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(String.bridgeJSStackPop(), Int.bridgeJSStackPop()) + default: + fatalError("Unknown API.NetworkingResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .failure(let param0, let param1): + param0.bridgeJSStackPush() + param1.bridgeJSStackPush() + return Int32(1) + } + } +} + +extension AllTypesResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> AllTypesResult { + switch caseId { + case 0: + return .structPayload(Address.bridgeJSStackPop()) + case 1: + return .classPayload(Greeter.bridgeJSStackPop()) + case 2: + return .jsObjectPayload(JSObject.bridgeJSStackPop()) + case 3: + return .nestedEnum(APIResult.bridgeJSStackPop()) + case 4: + return .arrayPayload([Int].bridgeJSStackPop()) + case 5: + return .jsClassPayload(Foo(unsafelyWrapping: JSObject.bridgeJSStackPop())) + case 6: + return .empty + default: + fatalError("Unknown AllTypesResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .structPayload(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .classPayload(let param0): + param0.bridgeJSStackPush() + return Int32(1) + case .jsObjectPayload(let param0): + param0.bridgeJSStackPush() + return Int32(2) + case .nestedEnum(let param0): + param0.bridgeJSStackPush() + return Int32(3) + case .arrayPayload(let param0): + param0.bridgeJSStackPush() + return Int32(4) + case .jsClassPayload(let param0): + param0.jsObject.bridgeJSStackPush() + return Int32(5) + case .empty: + return Int32(6) + } + } +} + +extension TypedPayloadResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> TypedPayloadResult { + switch caseId { + case 0: + return .precision(Precision.bridgeJSStackPop()) + case 1: + return .direction(Direction.bridgeJSStackPop()) + case 2: + return .optPrecision(Optional.bridgeJSStackPop()) + case 3: + return .optDirection(Optional.bridgeJSStackPop()) + case 4: + return .empty + default: + fatalError("Unknown TypedPayloadResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .precision(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .direction(let param0): + param0.bridgeJSStackPush() + return Int32(1) + case .optPrecision(let param0): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + return Int32(2) + case .optDirection(let param0): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + return Int32(3) + case .empty: + return Int32(4) + } + } +} + +extension StaticCalculator: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> StaticCalculator { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> StaticCalculator { + return StaticCalculator(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .scientific + case 1: + self = .basic + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .scientific: + return 0 + case .basic: + return 1 + } + } +} + +@_expose(wasm, "bjs_StaticCalculator_static_roundtrip") +@_cdecl("bjs_StaticCalculator_static_roundtrip") +public func _bjs_StaticCalculator_static_roundtrip(_ value: Int32) -> Int32 { + #if arch(wasm32) + let ret = StaticCalculator.roundtrip(_: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticUtils_Nested_static_roundtrip") +@_cdecl("bjs_StaticUtils_Nested_static_roundtrip") +public func _bjs_StaticUtils_Nested_static_roundtrip(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + let ret = StaticUtils.Nested.roundtrip(_: String.bridgeJSLiftParameter(valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Services_Graph_GraphOperations_static_createGraph") +@_cdecl("bjs_Services_Graph_GraphOperations_static_createGraph") +public func _bjs_Services_Graph_GraphOperations_static_createGraph(_ rootId: Int32) -> Int32 { + #if arch(wasm32) + let ret = GraphOperations.createGraph(rootId: Int.bridgeJSLiftParameter(rootId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Services_Graph_GraphOperations_static_nodeCount") +@_cdecl("bjs_Services_Graph_GraphOperations_static_nodeCount") +public func _bjs_Services_Graph_GraphOperations_static_nodeCount(_ graphId: Int32) -> Int32 { + #if arch(wasm32) + let ret = GraphOperations.nodeCount(graphId: Int.bridgeJSLiftParameter(graphId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension StaticPropertyEnum: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> StaticPropertyEnum { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> StaticPropertyEnum { + return StaticPropertyEnum(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .option1 + case 1: + self = .option2 + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .option1: + return 0 + case .option2: + return 1 + } + } +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_enumProperty_get") +@_cdecl("bjs_StaticPropertyEnum_static_enumProperty_get") +public func _bjs_StaticPropertyEnum_static_enumProperty_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyEnum.enumProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_enumProperty_set") +@_cdecl("bjs_StaticPropertyEnum_static_enumProperty_set") +public func _bjs_StaticPropertyEnum_static_enumProperty_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + StaticPropertyEnum.enumProperty = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_enumConstant_get") +@_cdecl("bjs_StaticPropertyEnum_static_enumConstant_get") +public func _bjs_StaticPropertyEnum_static_enumConstant_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyEnum.enumConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_enumBool_get") +@_cdecl("bjs_StaticPropertyEnum_static_enumBool_get") +public func _bjs_StaticPropertyEnum_static_enumBool_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyEnum.enumBool + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_enumBool_set") +@_cdecl("bjs_StaticPropertyEnum_static_enumBool_set") +public func _bjs_StaticPropertyEnum_static_enumBool_set(_ value: Int32) -> Void { + #if arch(wasm32) + StaticPropertyEnum.enumBool = Bool.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_enumVariable_get") +@_cdecl("bjs_StaticPropertyEnum_static_enumVariable_get") +public func _bjs_StaticPropertyEnum_static_enumVariable_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyEnum.enumVariable + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_enumVariable_set") +@_cdecl("bjs_StaticPropertyEnum_static_enumVariable_set") +public func _bjs_StaticPropertyEnum_static_enumVariable_set(_ value: Int32) -> Void { + #if arch(wasm32) + StaticPropertyEnum.enumVariable = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_computedReadonly_get") +@_cdecl("bjs_StaticPropertyEnum_static_computedReadonly_get") +public func _bjs_StaticPropertyEnum_static_computedReadonly_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyEnum.computedReadonly + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_computedReadWrite_get") +@_cdecl("bjs_StaticPropertyEnum_static_computedReadWrite_get") +public func _bjs_StaticPropertyEnum_static_computedReadWrite_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyEnum.computedReadWrite + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_computedReadWrite_set") +@_cdecl("bjs_StaticPropertyEnum_static_computedReadWrite_set") +public func _bjs_StaticPropertyEnum_static_computedReadWrite_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + StaticPropertyEnum.computedReadWrite = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyNamespace_static_namespaceProperty_get") +@_cdecl("bjs_StaticPropertyNamespace_static_namespaceProperty_get") +public func _bjs_StaticPropertyNamespace_static_namespaceProperty_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyNamespace.namespaceProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyNamespace_static_namespaceProperty_set") +@_cdecl("bjs_StaticPropertyNamespace_static_namespaceProperty_set") +public func _bjs_StaticPropertyNamespace_static_namespaceProperty_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + StaticPropertyNamespace.namespaceProperty = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyNamespace_static_namespaceConstant_get") +@_cdecl("bjs_StaticPropertyNamespace_static_namespaceConstant_get") +public func _bjs_StaticPropertyNamespace_static_namespaceConstant_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyNamespace.namespaceConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyNamespace_NestedProperties_static_nestedProperty_get") +@_cdecl("bjs_StaticPropertyNamespace_NestedProperties_static_nestedProperty_get") +public func _bjs_StaticPropertyNamespace_NestedProperties_static_nestedProperty_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyNamespace.NestedProperties.nestedProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyNamespace_NestedProperties_static_nestedProperty_set") +@_cdecl("bjs_StaticPropertyNamespace_NestedProperties_static_nestedProperty_set") +public func _bjs_StaticPropertyNamespace_NestedProperties_static_nestedProperty_set(_ value: Int32) -> Void { + #if arch(wasm32) + StaticPropertyNamespace.NestedProperties.nestedProperty = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyNamespace_NestedProperties_static_nestedConstant_get") +@_cdecl("bjs_StaticPropertyNamespace_NestedProperties_static_nestedConstant_get") +public func _bjs_StaticPropertyNamespace_NestedProperties_static_nestedConstant_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyNamespace.NestedProperties.nestedConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyNamespace_NestedProperties_static_nestedDouble_get") +@_cdecl("bjs_StaticPropertyNamespace_NestedProperties_static_nestedDouble_get") +public func _bjs_StaticPropertyNamespace_NestedProperties_static_nestedDouble_get() -> Float64 { + #if arch(wasm32) + let ret = StaticPropertyNamespace.NestedProperties.nestedDouble + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyNamespace_NestedProperties_static_nestedDouble_set") +@_cdecl("bjs_StaticPropertyNamespace_NestedProperties_static_nestedDouble_set") +public func _bjs_StaticPropertyNamespace_NestedProperties_static_nestedDouble_set(_ value: Float64) -> Void { + #if arch(wasm32) + StaticPropertyNamespace.NestedProperties.nestedDouble = Double.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> OptionalAllTypesResult { + switch caseId { + case 0: + return .optStruct(Optional
.bridgeJSStackPop()) + case 1: + return .optClass(Optional.bridgeJSStackPop()) + case 2: + return .optJSObject(Optional.bridgeJSStackPop()) + case 3: + return .optNestedEnum(Optional.bridgeJSStackPop()) + case 4: + return .optArray(Optional<[Int]>.bridgeJSStackPop()) + case 5: + return .optJsClass(Optional.bridgeJSStackPop().map { Foo(unsafelyWrapping: $0) }) + case 6: + return .empty + default: + fatalError("Unknown OptionalAllTypesResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .optStruct(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .optClass(let param0): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + return Int32(1) + case .optJSObject(let param0): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + return Int32(2) + case .optNestedEnum(let param0): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + return Int32(3) + case .optArray(let param0): + param0.bridgeJSStackPush() + return Int32(4) + case .optJsClass(let param0): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.jsObject.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + return Int32(5) + case .empty: + return Int32(6) + } + } +} + +extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> APIOptionalResult { + switch caseId { + case 0: + return .success(Optional.bridgeJSStackPop()) + case 1: + return .failure(Optional.bridgeJSStackPop(), Optional.bridgeJSStackPop()) + case 2: + return .status(Optional.bridgeJSStackPop(), Optional.bridgeJSStackPop(), Optional.bridgeJSStackPop()) + default: + fatalError("Unknown APIOptionalResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + return Int32(0) + case .failure(let param0, let param1): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + let __bjs_isSome_param1 = param1 != nil + if let __bjs_unwrapped_param1 = param1 { + __bjs_unwrapped_param1.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) + return Int32(1) + case .status(let param0, let param1, let param2): + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + __bjs_unwrapped_param0.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0) + let __bjs_isSome_param1 = param1 != nil + if let __bjs_unwrapped_param1 = param1 { + __bjs_unwrapped_param1.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param1 ? 1 : 0) + let __bjs_isSome_param2 = param2 != nil + if let __bjs_unwrapped_param2 = param2 { + __bjs_unwrapped_param2.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_param2 ? 1 : 0) + return Int32(2) + } + } +} + +extension Point: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Point { + let y = Int.bridgeJSStackPop() + let x = Int.bridgeJSStackPop() + return Point(x: x, y: y) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.x.bridgeJSStackPush() + self.y.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Point(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> PointerFields { + let mutPtr = UnsafeMutablePointer.bridgeJSStackPop() + let ptr = UnsafePointer.bridgeJSStackPop() + let opaque = OpaquePointer.bridgeJSStackPop() + let mutRaw = UnsafeMutableRawPointer.bridgeJSStackPop() + let raw = UnsafeRawPointer.bridgeJSStackPop() + return PointerFields(raw: raw, mutRaw: mutRaw, opaque: opaque, ptr: ptr, mutPtr: mutPtr) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.raw.bridgeJSStackPush() + self.mutRaw.bridgeJSStackPush() + self.opaque.bridgeJSStackPush() + self.ptr.bridgeJSStackPush() + self.mutPtr.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_PointerFields(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> DataPoint { + let optFlag = Optional.bridgeJSStackPop() + let optCount = Optional.bridgeJSStackPop() + let label = String.bridgeJSStackPop() + let y = Double.bridgeJSStackPop() + let x = Double.bridgeJSStackPop() + return DataPoint(x: x, y: y, label: label, optCount: optCount, optFlag: optFlag) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.x.bridgeJSStackPush() + self.y.bridgeJSStackPush() + self.label.bridgeJSStackPush() + let __bjs_isSome_optCount = self.optCount != nil + if let __bjs_unwrapped_optCount = self.optCount { + __bjs_unwrapped_optCount.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_optCount ? 1 : 0) + let __bjs_isSome_optFlag = self.optFlag != nil + if let __bjs_unwrapped_optFlag = self.optFlag { + __bjs_unwrapped_optFlag.bridgeJSStackPush() + } + _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.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 { + #if arch(wasm32) + let ret = DataPoint(x: Double.bridgeJSLiftParameter(x), y: Double.bridgeJSLiftParameter(y), label: String.bridgeJSLiftParameter(labelBytes, labelLength), optCount: Optional.bridgeJSLiftParameter(optCountIsSome, optCountValue), optFlag: Optional.bridgeJSLiftParameter(optFlagIsSome, optFlagValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension PublicPoint: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> PublicPoint { + let y = Int.bridgeJSStackPop() + let x = Int.bridgeJSStackPop() + return PublicPoint(x: x, y: y) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.x.bridgeJSStackPush() + self.y.bridgeJSStackPush() + } + + public init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_PublicPoint(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + public func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_PublicPoint())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_PublicPoint") +fileprivate func _bjs_struct_lower_PublicPoint(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_PublicPoint(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_PublicPoint") +fileprivate func _bjs_struct_lift_PublicPoint() -> Int32 +#else +fileprivate func _bjs_struct_lift_PublicPoint() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_PublicPoint_init") +@_cdecl("bjs_PublicPoint_init") +public func _bjs_PublicPoint_init(_ x: Int32, _ y: Int32) -> Void { + #if arch(wasm32) + let ret = PublicPoint(x: Int.bridgeJSLiftParameter(x), y: Int.bridgeJSLiftParameter(y)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Address: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Address { + let zipCode = Optional.bridgeJSStackPop() + let city = String.bridgeJSStackPop() + let street = String.bridgeJSStackPop() + return Address(street: street, city: city, zipCode: zipCode) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.street.bridgeJSStackPush() + self.city.bridgeJSStackPush() + let __bjs_isSome_zipCode = self.zipCode != nil + if let __bjs_unwrapped_zipCode = self.zipCode { + __bjs_unwrapped_zipCode.bridgeJSStackPush() + } + _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) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> Contact { + let secondaryAddress = Optional
.bridgeJSStackPop() + let email = Optional.bridgeJSStackPop() + let address = Address.bridgeJSStackPop() + let age = Int.bridgeJSStackPop() + let name = String.bridgeJSStackPop() + return Contact(name: name, age: age, address: address, email: email, secondaryAddress: secondaryAddress) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.name.bridgeJSStackPush() + self.age.bridgeJSStackPush() + self.address.bridgeJSStackPush() + let __bjs_isSome_email = self.email != nil + if let __bjs_unwrapped_email = self.email { + __bjs_unwrapped_email.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_email ? 1 : 0) + self.secondaryAddress.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Contact(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> Config { + let status = Status.bridgeJSStackPop() + let direction = Optional.bridgeJSStackPop() + let theme = Optional.bridgeJSStackPop() + let name = String.bridgeJSStackPop() + return Config(name: name, theme: theme, direction: direction, status: status) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.name.bridgeJSStackPush() + let __bjs_isSome_theme = self.theme != nil + if let __bjs_unwrapped_theme = self.theme { + __bjs_unwrapped_theme.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_theme ? 1 : 0) + let __bjs_isSome_direction = self.direction != nil + if let __bjs_unwrapped_direction = self.direction { + __bjs_unwrapped_direction.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_direction ? 1 : 0) + self.status.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_Config(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> SessionData { + let owner = Optional.bridgeJSStackPop() + let id = Int.bridgeJSStackPop() + return SessionData(id: id, owner: owner) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.id.bridgeJSStackPush() + let __bjs_isSome_owner = self.owner != nil + if let __bjs_unwrapped_owner = self.owner { + __bjs_unwrapped_owner.bridgeJSStackPush() + } + _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.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> ValidationReport { + let outcome = Optional.bridgeJSStackPop() + let status = Optional.bridgeJSStackPop() + let result = APIResult.bridgeJSStackPop() + let id = Int.bridgeJSStackPop() + return ValidationReport(id: id, result: result, status: status, outcome: outcome) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.id.bridgeJSStackPush() + self.result.bridgeJSStackPush() + let __bjs_isSome_status = self.status != nil + if let __bjs_unwrapped_status = self.status { + __bjs_unwrapped_status.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_status ? 1 : 0) + let __bjs_isSome_outcome = self.outcome != nil + if let __bjs_unwrapped_outcome = self.outcome { + __bjs_unwrapped_outcome.bridgeJSStackPush() + } + _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.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> AdvancedConfig { + let overrideDefaults = Optional.bridgeJSStackPop() + let defaults = ConfigStruct.bridgeJSStackPop() + let location = Optional.bridgeJSStackPop() + let metadata = Optional.bridgeJSStackPop() + let result = Optional.bridgeJSStackPop() + let status = Status.bridgeJSStackPop() + let theme = Theme.bridgeJSStackPop() + let enabled = Bool.bridgeJSStackPop() + let title = String.bridgeJSStackPop() + let id = Int.bridgeJSStackPop() + 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 bridgeJSStackPush() { + self.id.bridgeJSStackPush() + self.title.bridgeJSStackPush() + self.enabled.bridgeJSStackPush() + self.theme.bridgeJSStackPush() + self.status.bridgeJSStackPush() + let __bjs_isSome_result = self.result != nil + if let __bjs_unwrapped_result = self.result { + __bjs_unwrapped_result.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_result ? 1 : 0) + let __bjs_isSome_metadata = self.metadata != nil + if let __bjs_unwrapped_metadata = self.metadata { + __bjs_unwrapped_metadata.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_metadata ? 1 : 0) + self.location.bridgeJSStackPush() + self.defaults.bridgeJSStackPush() + self.overrideDefaults.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_AdvancedConfig(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> MeasurementConfig { + let optionalRatio = Optional.bridgeJSStackPop() + let optionalPrecision = Optional.bridgeJSStackPop() + let ratio = Ratio.bridgeJSStackPop() + let precision = Precision.bridgeJSStackPop() + return MeasurementConfig(precision: precision, ratio: ratio, optionalPrecision: optionalPrecision, optionalRatio: optionalRatio) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.precision.bridgeJSStackPush() + self.ratio.bridgeJSStackPush() + let __bjs_isSome_optionalPrecision = self.optionalPrecision != nil + if let __bjs_unwrapped_optionalPrecision = self.optionalPrecision { + __bjs_unwrapped_optionalPrecision.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_optionalPrecision ? 1 : 0) + let __bjs_isSome_optionalRatio = self.optionalRatio != nil + if let __bjs_unwrapped_optionalRatio = self.optionalRatio { + __bjs_unwrapped_optionalRatio.bridgeJSStackPush() + } + _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) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> MathOperations { + let baseValue = Double.bridgeJSStackPop() + return MathOperations(baseValue: baseValue) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.baseValue.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_MathOperations(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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") +public func _bjs_MathOperations_init(_ baseValue: Float64) -> Void { + #if arch(wasm32) + let ret = MathOperations(baseValue: Double.bridgeJSLiftParameter(baseValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathOperations_add") +@_cdecl("bjs_MathOperations_add") +public func _bjs_MathOperations_add(_ a: Float64, _ b: Float64) -> Float64 { + #if arch(wasm32) + let ret = MathOperations.bridgeJSLiftParameter().add(a: Double.bridgeJSLiftParameter(a), b: Double.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathOperations_multiply") +@_cdecl("bjs_MathOperations_multiply") +public func _bjs_MathOperations_multiply(_ a: Float64, _ b: Float64) -> Float64 { + #if arch(wasm32) + let ret = MathOperations.bridgeJSLiftParameter().multiply(a: Double.bridgeJSLiftParameter(a), b: Double.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathOperations_static_subtract") +@_cdecl("bjs_MathOperations_static_subtract") +public func _bjs_MathOperations_static_subtract(_ a: Float64, _ b: Float64) -> Float64 { + #if arch(wasm32) + let ret = MathOperations.subtract(a: Double.bridgeJSLiftParameter(a), b: Double.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension CopyableCart: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> CopyableCart { + let note = Optional.bridgeJSStackPop() + let x = Int.bridgeJSStackPop() + return CopyableCart(x: x, note: note) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.x.bridgeJSStackPush() + let __bjs_isSome_note = self.note != nil + if let __bjs_unwrapped_note = self.note { + __bjs_unwrapped_note.bridgeJSStackPush() + } + _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.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_CopyableCart())) + } +} + +#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 + +#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 bridgeJSStackPop() -> CopyableCartItem { + let quantity = Int.bridgeJSStackPop() + let sku = String.bridgeJSStackPop() + return CopyableCartItem(sku: sku, quantity: quantity) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.sku.bridgeJSStackPush() + self.quantity.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_CopyableCartItem(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> CopyableNestedCart { + let shippingAddress = Optional
.bridgeJSStackPop() + let item = CopyableCartItem.bridgeJSStackPop() + let id = Int.bridgeJSStackPop() + return CopyableNestedCart(id: id, item: item, shippingAddress: shippingAddress) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.id.bridgeJSStackPush() + self.item.bridgeJSStackPush() + self.shippingAddress.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_CopyableNestedCart(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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 bridgeJSStackPop() -> ConfigStruct { + let value = Int.bridgeJSStackPop() + let name = String.bridgeJSStackPop() + return ConfigStruct(name: name, value: value) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.name.bridgeJSStackPush() + self.value.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_ConfigStruct(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + 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") +@_cdecl("bjs_ConfigStruct_static_defaultConfig_set") +public func _bjs_ConfigStruct_static_defaultConfig_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + ConfigStruct.defaultConfig = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConfigStruct_static_maxRetries_get") +@_cdecl("bjs_ConfigStruct_static_maxRetries_get") +public func _bjs_ConfigStruct_static_maxRetries_get() -> Int32 { + #if arch(wasm32) + let ret = ConfigStruct.maxRetries + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConfigStruct_static_timeout_get") +@_cdecl("bjs_ConfigStruct_static_timeout_get") +public func _bjs_ConfigStruct_static_timeout_get() -> Float64 { + #if arch(wasm32) + let ret = ConfigStruct.timeout + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConfigStruct_static_timeout_set") +@_cdecl("bjs_ConfigStruct_static_timeout_set") +public func _bjs_ConfigStruct_static_timeout_set(_ value: Float64) -> Void { + #if arch(wasm32) + ConfigStruct.timeout = Double.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConfigStruct_static_computedSetting_get") +@_cdecl("bjs_ConfigStruct_static_computedSetting_get") +public func _bjs_ConfigStruct_static_computedSetting_get() -> Void { + #if arch(wasm32) + let ret = ConfigStruct.computedSetting + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension JSObjectContainer: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> JSObjectContainer { + let optionalObject = Optional.bridgeJSStackPop() + let object = JSObject.bridgeJSStackPop() + return JSObjectContainer(object: object, optionalObject: optionalObject) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.object.bridgeJSStackPush() + let __bjs_isSome_optionalObject = self.optionalObject != nil + if let __bjs_unwrapped_optionalObject = self.optionalObject { + __bjs_unwrapped_optionalObject.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_optionalObject ? 1 : 0) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_JSObjectContainer(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_JSObjectContainer())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_JSObjectContainer") +fileprivate func _bjs_struct_lower_JSObjectContainer(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_JSObjectContainer(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_JSObjectContainer") +fileprivate func _bjs_struct_lift_JSObjectContainer() -> Int32 +#else +fileprivate func _bjs_struct_lift_JSObjectContainer() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +extension FooContainer: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> FooContainer { + let optionalFoo = Optional.bridgeJSStackPop().map { Foo(unsafelyWrapping: $0) } + let foo = Foo(unsafelyWrapping: JSObject.bridgeJSStackPop()) + return FooContainer(foo: foo, optionalFoo: optionalFoo) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.foo.jsObject.bridgeJSStackPush() + let __bjs_isSome_optionalFoo = self.optionalFoo != nil + if let __bjs_unwrapped_optionalFoo = self.optionalFoo { + __bjs_unwrapped_optionalFoo.jsObject.bridgeJSStackPush() + } + _swift_js_push_i32(__bjs_isSome_optionalFoo ? 1 : 0) + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_FooContainer(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_FooContainer())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_FooContainer") +fileprivate func _bjs_struct_lower_FooContainer(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_FooContainer(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_FooContainer") +fileprivate func _bjs_struct_lift_FooContainer() -> Int32 +#else +fileprivate func _bjs_struct_lift_FooContainer() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +extension ArrayMembers: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> ArrayMembers { + let optStrings = Optional<[String]>.bridgeJSStackPop() + let ints = [Int].bridgeJSStackPop() + return ArrayMembers(ints: ints, optStrings: optStrings) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.ints.bridgeJSStackPush() + self.optStrings.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + let __bjs_cleanupId = _bjs_struct_lower_ArrayMembers(jsObject.bridgeJSLowerParameter()) + defer { + _swift_js_struct_cleanup(__bjs_cleanupId) + } + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_ArrayMembers())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_ArrayMembers") +fileprivate func _bjs_struct_lower_ArrayMembers(_ objectId: Int32) -> Int32 +#else +fileprivate func _bjs_struct_lower_ArrayMembers(_ objectId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_ArrayMembers") +fileprivate func _bjs_struct_lift_ArrayMembers() -> Int32 +#else +fileprivate func _bjs_struct_lift_ArrayMembers() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_ArrayMembers_sumValues") +@_cdecl("bjs_ArrayMembers_sumValues") +public func _bjs_ArrayMembers_sumValues() -> Int32 { + #if arch(wasm32) + let ret = ArrayMembers.bridgeJSLiftParameter().sumValues(_: [Int].bridgeJSStackPop()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ArrayMembers_firstString") +@_cdecl("bjs_ArrayMembers_firstString") +public func _bjs_ArrayMembers_firstString() -> Void { + #if arch(wasm32) + let ret = ArrayMembers.bridgeJSLiftParameter().firstString(_: [String].bridgeJSStackPop()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripVoid") +@_cdecl("bjs_roundTripVoid") +public func _bjs_roundTripVoid() -> Void { + #if arch(wasm32) + roundTripVoid() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripInt") +@_cdecl("bjs_roundTripInt") +public func _bjs_roundTripInt(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundTripInt(v: Int.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #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 { + #if arch(wasm32) + let ret = roundTripFloat(v: Float.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripDouble") +@_cdecl("bjs_roundTripDouble") +public func _bjs_roundTripDouble(_ v: Float64) -> Float64 { + #if arch(wasm32) + let ret = roundTripDouble(v: Double.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripBool") +@_cdecl("bjs_roundTripBool") +public func _bjs_roundTripBool(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundTripBool(v: Bool.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripString") +@_cdecl("bjs_roundTripString") +public func _bjs_roundTripString(_ vBytes: Int32, _ vLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripString(v: String.bridgeJSLiftParameter(vBytes, vLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripSwiftHeapObject") +@_cdecl("bjs_roundTripSwiftHeapObject") +public func _bjs_roundTripSwiftHeapObject(_ v: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = roundTripSwiftHeapObject(v: Greeter.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #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 { + #if arch(wasm32) + let ret = roundTripJSObject(v: JSObject.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripDictionaryExport") +@_cdecl("bjs_roundTripDictionaryExport") +public func _bjs_roundTripDictionaryExport() -> Void { + #if arch(wasm32) + let ret = roundTripDictionaryExport(v: [String: Int].bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalDictionaryExport") +@_cdecl("bjs_roundTripOptionalDictionaryExport") +public func _bjs_roundTripOptionalDictionaryExport() -> Void { + #if arch(wasm32) + let ret = roundTripOptionalDictionaryExport(v: Optional<[String: String]>.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripJSValue") +@_cdecl("bjs_roundTripJSValue") +public func _bjs_roundTripJSValue(_ vKind: Int32, _ vPayload1: Int32, _ vPayload2: Float64) -> Void { + #if arch(wasm32) + let ret = roundTripJSValue(v: JSValue.bridgeJSLiftParameter(vKind, vPayload1, vPayload2)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalJSValue") +@_cdecl("bjs_roundTripOptionalJSValue") +public func _bjs_roundTripOptionalJSValue(_ vIsSome: Int32, _ vKind: Int32, _ vPayload1: Int32, _ vPayload2: Float64) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalJSValue(v: Optional.bridgeJSLiftParameter(vIsSome, vKind, vPayload1, vPayload2)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripJSValueArray") +@_cdecl("bjs_roundTripJSValueArray") +public func _bjs_roundTripJSValueArray() -> Void { + #if arch(wasm32) + let ret = roundTripJSValueArray(v: [JSValue].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalJSValueArray") +@_cdecl("bjs_roundTripOptionalJSValueArray") +public func _bjs_roundTripOptionalJSValueArray() -> Void { + #if arch(wasm32) + let ret = roundTripOptionalJSValueArray(v: Optional<[JSValue]>.bridgeJSLiftParameter()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeImportedFoo") +@_cdecl("bjs_makeImportedFoo") +public func _bjs_makeImportedFoo(_ valueBytes: Int32, _ valueLength: Int32) -> Int32 { + #if arch(wasm32) + do { + let ret = try makeImportedFoo(value: String.bridgeJSLiftParameter(valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + } catch let error { + if let error = error.thrownValue.object { + withExtendedLifetime(error) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } else { + let jsError = JSError(message: String(describing: error)) + withExtendedLifetime(jsError.jsObject) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } + return 0 + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_throwsSwiftError") +@_cdecl("bjs_throwsSwiftError") +public func _bjs_throwsSwiftError(_ shouldThrow: Int32) -> Void { + #if arch(wasm32) + do { + try throwsSwiftError(shouldThrow: Bool.bridgeJSLiftParameter(shouldThrow)) + } catch let error { + if let error = error.thrownValue.object { + withExtendedLifetime(error) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } else { + let jsError = JSError(message: String(describing: error)) + withExtendedLifetime(jsError.jsObject) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } + return + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_throwsWithIntResult") +@_cdecl("bjs_throwsWithIntResult") +public func _bjs_throwsWithIntResult() -> Int32 { + #if arch(wasm32) + do { + let ret = try throwsWithIntResult() + return ret.bridgeJSLowerReturn() + } catch let error { + if let error = error.thrownValue.object { + withExtendedLifetime(error) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } else { + let jsError = JSError(message: String(describing: error)) + withExtendedLifetime(jsError.jsObject) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } + return 0 + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_throwsWithStringResult") +@_cdecl("bjs_throwsWithStringResult") +public func _bjs_throwsWithStringResult() -> Void { + #if arch(wasm32) + do { + let ret = try throwsWithStringResult() + return ret.bridgeJSLowerReturn() + } catch let error { + if let error = error.thrownValue.object { + withExtendedLifetime(error) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } else { + let jsError = JSError(message: String(describing: error)) + withExtendedLifetime(jsError.jsObject) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } + return + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_throwsWithBoolResult") +@_cdecl("bjs_throwsWithBoolResult") +public func _bjs_throwsWithBoolResult() -> Int32 { + #if arch(wasm32) + do { + let ret = try throwsWithBoolResult() + return ret.bridgeJSLowerReturn() + } catch let error { + if let error = error.thrownValue.object { + withExtendedLifetime(error) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } else { + let jsError = JSError(message: String(describing: error)) + withExtendedLifetime(jsError.jsObject) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } + return 0 + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_throwsWithFloatResult") +@_cdecl("bjs_throwsWithFloatResult") +public func _bjs_throwsWithFloatResult() -> Float32 { + #if arch(wasm32) + do { + let ret = try throwsWithFloatResult() + return ret.bridgeJSLowerReturn() + } catch let error { + if let error = error.thrownValue.object { + withExtendedLifetime(error) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } else { + let jsError = JSError(message: String(describing: error)) + withExtendedLifetime(jsError.jsObject) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } + return 0.0 + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_throwsWithDoubleResult") +@_cdecl("bjs_throwsWithDoubleResult") +public func _bjs_throwsWithDoubleResult() -> Float64 { + #if arch(wasm32) + do { + let ret = try throwsWithDoubleResult() + return ret.bridgeJSLowerReturn() + } catch let error { + if let error = error.thrownValue.object { + withExtendedLifetime(error) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } else { + let jsError = JSError(message: String(describing: error)) + withExtendedLifetime(jsError.jsObject) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } + return 0.0 + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_throwsWithSwiftHeapObjectResult") +@_cdecl("bjs_throwsWithSwiftHeapObjectResult") +public func _bjs_throwsWithSwiftHeapObjectResult() -> UnsafeMutableRawPointer { + #if arch(wasm32) + do { + let ret = try throwsWithSwiftHeapObjectResult() + return ret.bridgeJSLowerReturn() + } catch let error { + if let error = error.thrownValue.object { + withExtendedLifetime(error) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } else { + let jsError = JSError(message: String(describing: error)) + withExtendedLifetime(jsError.jsObject) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } + return UnsafeMutableRawPointer(bitPattern: -1).unsafelyUnwrapped + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_throwsWithJSObjectResult") +@_cdecl("bjs_throwsWithJSObjectResult") +public func _bjs_throwsWithJSObjectResult() -> Int32 { + #if arch(wasm32) + do { + let ret = try throwsWithJSObjectResult() + return ret.bridgeJSLowerReturn() + } catch let error { + if let error = error.thrownValue.object { + withExtendedLifetime(error) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } else { + let jsError = JSError(message: String(describing: error)) + withExtendedLifetime(jsError.jsObject) { + _swift_js_throw(Int32(bitPattern: $0.id)) + } + } + return 0 + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripVoid") +@_cdecl("bjs_asyncRoundTripVoid") +public func _bjs_asyncRoundTripVoid() -> Int32 { + #if arch(wasm32) + let ret = JSPromise.async { + await asyncRoundTripVoid() + }.jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripInt") +@_cdecl("bjs_asyncRoundTripInt") +public func _bjs_asyncRoundTripInt(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = JSPromise.async { + return await asyncRoundTripInt(v: Int.bridgeJSLiftParameter(v)).jsValue + }.jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripFloat") +@_cdecl("bjs_asyncRoundTripFloat") +public func _bjs_asyncRoundTripFloat(_ v: Float32) -> Int32 { + #if arch(wasm32) + let ret = JSPromise.async { + return await asyncRoundTripFloat(v: Float.bridgeJSLiftParameter(v)).jsValue + }.jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripDouble") +@_cdecl("bjs_asyncRoundTripDouble") +public func _bjs_asyncRoundTripDouble(_ v: Float64) -> Int32 { + #if arch(wasm32) + let ret = JSPromise.async { + return await asyncRoundTripDouble(v: Double.bridgeJSLiftParameter(v)).jsValue + }.jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripBool") +@_cdecl("bjs_asyncRoundTripBool") +public func _bjs_asyncRoundTripBool(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = JSPromise.async { + return await asyncRoundTripBool(v: Bool.bridgeJSLiftParameter(v)).jsValue + }.jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripString") +@_cdecl("bjs_asyncRoundTripString") +public func _bjs_asyncRoundTripString(_ vBytes: Int32, _ vLength: Int32) -> Int32 { + #if arch(wasm32) + let ret = JSPromise.async { + return await asyncRoundTripString(v: String.bridgeJSLiftParameter(vBytes, vLength)).jsValue + }.jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripSwiftHeapObject") +@_cdecl("bjs_asyncRoundTripSwiftHeapObject") +public func _bjs_asyncRoundTripSwiftHeapObject(_ v: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = JSPromise.async { + return await asyncRoundTripSwiftHeapObject(v: Greeter.bridgeJSLiftParameter(v)).jsValue + }.jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripJSObject") +@_cdecl("bjs_asyncRoundTripJSObject") +public func _bjs_asyncRoundTripJSObject(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = JSPromise.async { + return await asyncRoundTripJSObject(v: JSObject.bridgeJSLiftParameter(v)).jsValue + }.jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_takeGreeter") +@_cdecl("bjs_takeGreeter") +public func _bjs_takeGreeter(_ g: UnsafeMutableRawPointer, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + takeGreeter(g: Greeter.bridgeJSLiftParameter(g), name: String.bridgeJSLiftParameter(nameBytes, nameLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_createCalculator") +@_cdecl("bjs_createCalculator") +public func _bjs_createCalculator() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = createCalculator() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_useCalculator") +@_cdecl("bjs_useCalculator") +public func _bjs_useCalculator(_ calc: UnsafeMutableRawPointer, _ x: Int32, _ y: Int32) -> Int32 { + #if arch(wasm32) + let ret = useCalculator(calc: Calculator.bridgeJSLiftParameter(calc), x: Int.bridgeJSLiftParameter(x), y: Int.bridgeJSLiftParameter(y)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testGreeterToJSValue") +@_cdecl("bjs_testGreeterToJSValue") +public func _bjs_testGreeterToJSValue() -> Int32 { + #if arch(wasm32) + let ret = testGreeterToJSValue() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testCalculatorToJSValue") +@_cdecl("bjs_testCalculatorToJSValue") +public func _bjs_testCalculatorToJSValue() -> Int32 { + #if arch(wasm32) + let ret = testCalculatorToJSValue() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testSwiftClassAsJSValue") +@_cdecl("bjs_testSwiftClassAsJSValue") +public func _bjs_testSwiftClassAsJSValue(_ greeter: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = testSwiftClassAsJSValue(greeter: Greeter.bridgeJSLiftParameter(greeter)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setDirection") +@_cdecl("bjs_setDirection") +public func _bjs_setDirection(_ direction: Int32) -> Int32 { + #if arch(wasm32) + let ret = setDirection(_: Direction.bridgeJSLiftParameter(direction)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getDirection") +@_cdecl("bjs_getDirection") +public func _bjs_getDirection() -> Int32 { + #if arch(wasm32) + let ret = getDirection() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processDirection") +@_cdecl("bjs_processDirection") +public func _bjs_processDirection(_ input: Int32) -> Int32 { + #if arch(wasm32) + let ret = processDirection(_: Direction.bridgeJSLiftParameter(input)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setTheme") +@_cdecl("bjs_setTheme") +public func _bjs_setTheme(_ themeBytes: Int32, _ themeLength: Int32) -> Void { + #if arch(wasm32) + let ret = setTheme(_: Theme.bridgeJSLiftParameter(themeBytes, themeLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getTheme") +@_cdecl("bjs_getTheme") +public func _bjs_getTheme() -> Void { + #if arch(wasm32) + let ret = getTheme() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setHttpStatus") +@_cdecl("bjs_setHttpStatus") +public func _bjs_setHttpStatus(_ status: Int32) -> Int32 { + #if arch(wasm32) + let ret = setHttpStatus(_: HttpStatus.bridgeJSLiftParameter(status)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getHttpStatus") +@_cdecl("bjs_getHttpStatus") +public func _bjs_getHttpStatus() -> Int32 { + #if arch(wasm32) + let ret = getHttpStatus() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processTheme") +@_cdecl("bjs_processTheme") +public func _bjs_processTheme(_ themeBytes: Int32, _ themeLength: Int32) -> Int32 { + #if arch(wasm32) + let ret = processTheme(_: Theme.bridgeJSLiftParameter(themeBytes, themeLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setTSDirection") +@_cdecl("bjs_setTSDirection") +public func _bjs_setTSDirection(_ direction: Int32) -> Int32 { + #if arch(wasm32) + let ret = setTSDirection(_: TSDirection.bridgeJSLiftParameter(direction)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getTSDirection") +@_cdecl("bjs_getTSDirection") +public func _bjs_getTSDirection() -> Int32 { + #if arch(wasm32) + let ret = getTSDirection() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setTSTheme") +@_cdecl("bjs_setTSTheme") +public func _bjs_setTSTheme(_ themeBytes: Int32, _ themeLength: Int32) -> Void { + #if arch(wasm32) + let ret = setTSTheme(_: TSTheme.bridgeJSLiftParameter(themeBytes, themeLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getTSTheme") +@_cdecl("bjs_getTSTheme") +public func _bjs_getTSTheme() -> Void { + #if arch(wasm32) + let ret = getTSTheme() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripNetworkingAPIMethod") +@_cdecl("bjs_roundtripNetworkingAPIMethod") +public func _bjs_roundtripNetworkingAPIMethod(_ method: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripNetworkingAPIMethod(_: Networking.API.Method.bridgeJSLiftParameter(method)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripConfigurationLogLevel") +@_cdecl("bjs_roundtripConfigurationLogLevel") +public func _bjs_roundtripConfigurationLogLevel(_ levelBytes: Int32, _ levelLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundtripConfigurationLogLevel(_: Configuration.LogLevel.bridgeJSLiftParameter(levelBytes, levelLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripConfigurationPort") +@_cdecl("bjs_roundtripConfigurationPort") +public func _bjs_roundtripConfigurationPort(_ port: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripConfigurationPort(_: Configuration.Port.bridgeJSLiftParameter(port)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processConfigurationLogLevel") +@_cdecl("bjs_processConfigurationLogLevel") +public func _bjs_processConfigurationLogLevel(_ levelBytes: Int32, _ levelLength: Int32) -> Int32 { + #if arch(wasm32) + let ret = processConfigurationLogLevel(_: Configuration.LogLevel.bridgeJSLiftParameter(levelBytes, levelLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripInternalSupportedMethod") +@_cdecl("bjs_roundtripInternalSupportedMethod") +public func _bjs_roundtripInternalSupportedMethod(_ method: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripInternalSupportedMethod(_: Internal.SupportedMethod.bridgeJSLiftParameter(method)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripAPIResult") +@_cdecl("bjs_roundtripAPIResult") +public func _bjs_roundtripAPIResult(_ result: Int32) -> Void { + #if arch(wasm32) + let ret = roundtripAPIResult(result: APIResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAPIResultSuccess") +@_cdecl("bjs_makeAPIResultSuccess") +public func _bjs_makeAPIResultSuccess(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + let ret = makeAPIResultSuccess(_: String.bridgeJSLiftParameter(valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAPIResultFailure") +@_cdecl("bjs_makeAPIResultFailure") +public func _bjs_makeAPIResultFailure(_ value: Int32) -> Void { + #if arch(wasm32) + let ret = makeAPIResultFailure(_: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAPIResultInfo") +@_cdecl("bjs_makeAPIResultInfo") +public func _bjs_makeAPIResultInfo() -> Void { + #if arch(wasm32) + let ret = makeAPIResultInfo() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAPIResultFlag") +@_cdecl("bjs_makeAPIResultFlag") +public func _bjs_makeAPIResultFlag(_ value: Int32) -> Void { + #if arch(wasm32) + let ret = makeAPIResultFlag(_: Bool.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAPIResultRate") +@_cdecl("bjs_makeAPIResultRate") +public func _bjs_makeAPIResultRate(_ value: Float32) -> Void { + #if arch(wasm32) + let ret = makeAPIResultRate(_: Float.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAPIResultPrecise") +@_cdecl("bjs_makeAPIResultPrecise") +public func _bjs_makeAPIResultPrecise(_ value: Float64) -> Void { + #if arch(wasm32) + let ret = makeAPIResultPrecise(_: Double.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripComplexResult") +@_cdecl("bjs_roundtripComplexResult") +public func _bjs_roundtripComplexResult(_ result: Int32) -> Void { + #if arch(wasm32) + let ret = roundtripComplexResult(_: ComplexResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeComplexResultSuccess") +@_cdecl("bjs_makeComplexResultSuccess") +public func _bjs_makeComplexResultSuccess(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + let ret = makeComplexResultSuccess(_: String.bridgeJSLiftParameter(valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeComplexResultError") +@_cdecl("bjs_makeComplexResultError") +public func _bjs_makeComplexResultError(_ messageBytes: Int32, _ messageLength: Int32, _ code: Int32) -> Void { + #if arch(wasm32) + let ret = makeComplexResultError(_: String.bridgeJSLiftParameter(messageBytes, messageLength), _: Int.bridgeJSLiftParameter(code)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeComplexResultLocation") +@_cdecl("bjs_makeComplexResultLocation") +public func _bjs_makeComplexResultLocation(_ lat: Float64, _ lng: Float64, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = makeComplexResultLocation(_: Double.bridgeJSLiftParameter(lat), _: Double.bridgeJSLiftParameter(lng), _: String.bridgeJSLiftParameter(nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeComplexResultStatus") +@_cdecl("bjs_makeComplexResultStatus") +public func _bjs_makeComplexResultStatus(_ active: Int32, _ code: Int32, _ messageBytes: Int32, _ messageLength: Int32) -> Void { + #if arch(wasm32) + let ret = makeComplexResultStatus(_: Bool.bridgeJSLiftParameter(active), _: Int.bridgeJSLiftParameter(code), _: String.bridgeJSLiftParameter(messageBytes, messageLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeComplexResultCoordinates") +@_cdecl("bjs_makeComplexResultCoordinates") +public func _bjs_makeComplexResultCoordinates(_ x: Float64, _ y: Float64, _ z: Float64) -> Void { + #if arch(wasm32) + let ret = makeComplexResultCoordinates(_: Double.bridgeJSLiftParameter(x), _: Double.bridgeJSLiftParameter(y), _: Double.bridgeJSLiftParameter(z)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeComplexResultComprehensive") +@_cdecl("bjs_makeComplexResultComprehensive") +public func _bjs_makeComplexResultComprehensive(_ flag1: Int32, _ flag2: Int32, _ count1: Int32, _ count2: Int32, _ value1: Float64, _ value2: Float64, _ text1Bytes: Int32, _ text1Length: Int32, _ text2Bytes: Int32, _ text2Length: Int32, _ text3Bytes: Int32, _ text3Length: Int32) -> Void { + #if arch(wasm32) + let ret = makeComplexResultComprehensive(_: Bool.bridgeJSLiftParameter(flag1), _: Bool.bridgeJSLiftParameter(flag2), _: Int.bridgeJSLiftParameter(count1), _: Int.bridgeJSLiftParameter(count2), _: Double.bridgeJSLiftParameter(value1), _: Double.bridgeJSLiftParameter(value2), _: String.bridgeJSLiftParameter(text1Bytes, text1Length), _: String.bridgeJSLiftParameter(text2Bytes, text2Length), _: String.bridgeJSLiftParameter(text3Bytes, text3Length)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeComplexResultInfo") +@_cdecl("bjs_makeComplexResultInfo") +public func _bjs_makeComplexResultInfo() -> Void { + #if arch(wasm32) + let ret = makeComplexResultInfo() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeUtilitiesResultSuccess") +@_cdecl("bjs_makeUtilitiesResultSuccess") +public func _bjs_makeUtilitiesResultSuccess(_ messageBytes: Int32, _ messageLength: Int32) -> Void { + #if arch(wasm32) + let ret = makeUtilitiesResultSuccess(_: String.bridgeJSLiftParameter(messageBytes, messageLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeUtilitiesResultFailure") +@_cdecl("bjs_makeUtilitiesResultFailure") +public func _bjs_makeUtilitiesResultFailure(_ errorBytes: Int32, _ errorLength: Int32, _ code: Int32) -> Void { + #if arch(wasm32) + let ret = makeUtilitiesResultFailure(_: String.bridgeJSLiftParameter(errorBytes, errorLength), _: Int.bridgeJSLiftParameter(code)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeUtilitiesResultStatus") +@_cdecl("bjs_makeUtilitiesResultStatus") +public func _bjs_makeUtilitiesResultStatus(_ active: Int32, _ code: Int32, _ messageBytes: Int32, _ messageLength: Int32) -> Void { + #if arch(wasm32) + let ret = makeUtilitiesResultStatus(_: Bool.bridgeJSLiftParameter(active), _: Int.bridgeJSLiftParameter(code), _: String.bridgeJSLiftParameter(messageBytes, messageLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAPINetworkingResultSuccess") +@_cdecl("bjs_makeAPINetworkingResultSuccess") +public func _bjs_makeAPINetworkingResultSuccess(_ messageBytes: Int32, _ messageLength: Int32) -> Void { + #if arch(wasm32) + let ret = makeAPINetworkingResultSuccess(_: String.bridgeJSLiftParameter(messageBytes, messageLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAPINetworkingResultFailure") +@_cdecl("bjs_makeAPINetworkingResultFailure") +public func _bjs_makeAPINetworkingResultFailure(_ errorBytes: Int32, _ errorLength: Int32, _ code: Int32) -> Void { + #if arch(wasm32) + let ret = makeAPINetworkingResultFailure(_: String.bridgeJSLiftParameter(errorBytes, errorLength), _: Int.bridgeJSLiftParameter(code)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripUtilitiesResult") +@_cdecl("bjs_roundtripUtilitiesResult") +public func _bjs_roundtripUtilitiesResult(_ result: Int32) -> Void { + #if arch(wasm32) + let ret = roundtripUtilitiesResult(_: Utilities.Result.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripAPINetworkingResult") +@_cdecl("bjs_roundtripAPINetworkingResult") +public func _bjs_roundtripAPINetworkingResult(_ result: Int32) -> Void { + #if arch(wasm32) + let ret = roundtripAPINetworkingResult(_: API.NetworkingResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripAllTypesResult") +@_cdecl("bjs_roundTripAllTypesResult") +public func _bjs_roundTripAllTypesResult(_ result: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripAllTypesResult(_: AllTypesResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripTypedPayloadResult") +@_cdecl("bjs_roundTripTypedPayloadResult") +public func _bjs_roundTripTypedPayloadResult(_ result: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripTypedPayloadResult(_: TypedPayloadResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_createPropertyHolder") +@_cdecl("bjs_createPropertyHolder") +public func _bjs_createPropertyHolder(_ intValue: Int32, _ floatValue: Float32, _ doubleValue: Float64, _ boolValue: Int32, _ stringValueBytes: Int32, _ stringValueLength: Int32, _ jsObject: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = createPropertyHolder(intValue: Int.bridgeJSLiftParameter(intValue), floatValue: Float.bridgeJSLiftParameter(floatValue), doubleValue: Double.bridgeJSLiftParameter(doubleValue), boolValue: Bool.bridgeJSLiftParameter(boolValue), stringValue: String.bridgeJSLiftParameter(stringValueBytes, stringValueLength), jsObject: JSObject.bridgeJSLiftParameter(jsObject)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testPropertyHolder") +@_cdecl("bjs_testPropertyHolder") +public func _bjs_testPropertyHolder(_ holder: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = testPropertyHolder(holder: PropertyHolder.bridgeJSLiftParameter(holder)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_resetObserverCounts") +@_cdecl("bjs_resetObserverCounts") +public func _bjs_resetObserverCounts() -> Void { + #if arch(wasm32) + resetObserverCounts() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getObserverStats") +@_cdecl("bjs_getObserverStats") +public func _bjs_getObserverStats() -> Void { + #if arch(wasm32) + let ret = getObserverStats() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testStringDefault") +@_cdecl("bjs_testStringDefault") +public func _bjs_testStringDefault(_ messageBytes: Int32, _ messageLength: Int32) -> Void { + #if arch(wasm32) + let ret = testStringDefault(message: String.bridgeJSLiftParameter(messageBytes, messageLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testIntDefault") +@_cdecl("bjs_testIntDefault") +public func _bjs_testIntDefault(_ count: Int32) -> Int32 { + #if arch(wasm32) + let ret = testIntDefault(count: Int.bridgeJSLiftParameter(count)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testBoolDefault") +@_cdecl("bjs_testBoolDefault") +public func _bjs_testBoolDefault(_ flag: Int32) -> Int32 { + #if arch(wasm32) + let ret = testBoolDefault(flag: Bool.bridgeJSLiftParameter(flag)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testOptionalDefault") +@_cdecl("bjs_testOptionalDefault") +public func _bjs_testOptionalDefault(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = testOptionalDefault(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testMultipleDefaults") +@_cdecl("bjs_testMultipleDefaults") +public func _bjs_testMultipleDefaults(_ titleBytes: Int32, _ titleLength: Int32, _ count: Int32, _ enabled: Int32) -> Void { + #if arch(wasm32) + let ret = testMultipleDefaults(title: String.bridgeJSLiftParameter(titleBytes, titleLength), count: Int.bridgeJSLiftParameter(count), enabled: Bool.bridgeJSLiftParameter(enabled)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_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(_: [Int].bridgeJSStackPop()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_arrayWithOptionalDefault") +@_cdecl("bjs_arrayWithOptionalDefault") +public func _bjs_arrayWithOptionalDefault() -> Int32 { + #if arch(wasm32) + let ret = arrayWithOptionalDefault(_: Optional<[Int]>.bridgeJSLiftParameter()) + 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: [Int].bridgeJSStackPop(), 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) -> Int32 { + #if arch(wasm32) + let ret = makeFormatter(prefix: String.bridgeJSLiftParameter(prefixBytes, prefixLength)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAdder") +@_cdecl("bjs_makeAdder") +public func _bjs_makeAdder(_ base: Int32) -> Int32 { + #if arch(wasm32) + let ret = makeAdder(base: Int.bridgeJSLiftParameter(base)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #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(_: [Int].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [String].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [Double].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [Bool].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [Direction].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [Status].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [Theme].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [HttpStatus].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [DataPoint].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [Greeter].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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.bridgeJSStackPop()) + } + __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.bridgeJSStackPush() + } + _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.bridgeJSStackPop()) + } + __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.bridgeJSStackPush() + } + _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.bridgeJSStackPop()) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + __bjs_elem_ret.bridgeJSStackPush() + } + _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.bridgeJSStackPop()) + } + __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.bridgeJSStackPush() + } + _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.bridgeJSStackPop()) + } + __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.bridgeJSStackPush() + } + _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() -> Void { + #if arch(wasm32) + let ret = roundTripOptionalIntArrayType(_: Optional<[Int]>.bridgeJSLiftParameter()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalStringArrayType") +@_cdecl("bjs_roundTripOptionalStringArrayType") +public func _bjs_roundTripOptionalStringArrayType() -> Void { + #if arch(wasm32) + let ret = roundTripOptionalStringArrayType(_: Optional<[String]>.bridgeJSLiftParameter()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalGreeterArrayType") +@_cdecl("bjs_roundTripOptionalGreeterArrayType") +public func _bjs_roundTripOptionalGreeterArrayType() -> Void { + #if arch(wasm32) + let ret = roundTripOptionalGreeterArrayType(_: Optional<[Greeter]>.bridgeJSLiftParameter()) + ret.bridgeJSStackPush() + #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(_: [[Int]].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [[String]].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [[Double]].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [[Bool]].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [[DataPoint]].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [[Direction]].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #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(_: [[Greeter]].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripUnsafeRawPointerArray") +@_cdecl("bjs_roundTripUnsafeRawPointerArray") +public func _bjs_roundTripUnsafeRawPointerArray() -> Void { + #if arch(wasm32) + let ret = roundTripUnsafeRawPointerArray(_: [UnsafeRawPointer].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripUnsafeMutableRawPointerArray") +@_cdecl("bjs_roundTripUnsafeMutableRawPointerArray") +public func _bjs_roundTripUnsafeMutableRawPointerArray() -> Void { + #if arch(wasm32) + let ret = roundTripUnsafeMutableRawPointerArray(_: [UnsafeMutableRawPointer].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOpaquePointerArray") +@_cdecl("bjs_roundTripOpaquePointerArray") +public func _bjs_roundTripOpaquePointerArray() -> Void { + #if arch(wasm32) + let ret = roundTripOpaquePointerArray(_: [OpaquePointer].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripUnsafePointerArray") +@_cdecl("bjs_roundTripUnsafePointerArray") +public func _bjs_roundTripUnsafePointerArray() -> Void { + #if arch(wasm32) + let ret = roundTripUnsafePointerArray(_: [UnsafePointer].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripUnsafeMutablePointerArray") +@_cdecl("bjs_roundTripUnsafeMutablePointerArray") +public func _bjs_roundTripUnsafeMutablePointerArray() -> Void { + #if arch(wasm32) + let ret = roundTripUnsafeMutablePointerArray(_: [UnsafeMutablePointer].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_consumeDataProcessorArrayType") +@_cdecl("bjs_consumeDataProcessorArrayType") +public func _bjs_consumeDataProcessorArrayType() -> Int32 { + #if arch(wasm32) + let ret = consumeDataProcessorArrayType(_: [AnyDataProcessor].bridgeJSStackPop()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripDataProcessorArrayType") +@_cdecl("bjs_roundTripDataProcessorArrayType") +public func _bjs_roundTripDataProcessorArrayType() -> Void { + #if arch(wasm32) + let ret = roundTripDataProcessorArrayType(_: [AnyDataProcessor].bridgeJSStackPop()) + ret.map { $0 as! AnyDataProcessor }.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripJSObjectArray") +@_cdecl("bjs_roundTripJSObjectArray") +public func _bjs_roundTripJSObjectArray() -> Void { + #if arch(wasm32) + let ret = roundTripJSObjectArray(_: [JSObject].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalJSObjectArray") +@_cdecl("bjs_roundTripOptionalJSObjectArray") +public func _bjs_roundTripOptionalJSObjectArray() -> Void { + #if arch(wasm32) + let ret = roundTripOptionalJSObjectArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0..<__count { + __result.append(Optional.bridgeJSStackPop()) + } + __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.bridgeJSStackPush() + } + _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_roundTripFooArray") +@_cdecl("bjs_roundTripFooArray") +public func _bjs_roundTripFooArray() -> Void { + #if arch(wasm32) + let ret = roundTripFooArray(_: [JSObject].bridgeJSStackPop().map { Foo(unsafelyWrapping: $0) }) + ret.map { $0.jsObject }.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalFooArray") +@_cdecl("bjs_roundTripOptionalFooArray") +public func _bjs_roundTripOptionalFooArray() -> Void { + #if arch(wasm32) + let ret = roundTripOptionalFooArray(_: { + let __count = Int(_swift_js_pop_i32()) + var __result: [Optional] = [] + __result.reserveCapacity(__count) + for _ in 0..<__count { + __result.append(Optional.bridgeJSStackPop().map { Foo(unsafelyWrapping: $0) }) + } + __result.reverse() + return __result + }()) + for __bjs_elem_ret in ret { + let __bjs_isSome_ret_elem = __bjs_elem_ret != nil + if let __bjs_unwrapped_ret_elem = __bjs_elem_ret { + __bjs_unwrapped_ret_elem.jsObject.bridgeJSStackPush() + } + _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_roundTripOptionalString") +@_cdecl("bjs_roundTripOptionalString") +public func _bjs_roundTripOptionalString(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalString(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalInt") +@_cdecl("bjs_roundTripOptionalInt") +public func _bjs_roundTripOptionalInt(_ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalInt(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalBool") +@_cdecl("bjs_roundTripOptionalBool") +public func _bjs_roundTripOptionalBool(_ flagIsSome: Int32, _ flagValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalBool(flag: Optional.bridgeJSLiftParameter(flagIsSome, flagValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalFloat") +@_cdecl("bjs_roundTripOptionalFloat") +public func _bjs_roundTripOptionalFloat(_ numberIsSome: Int32, _ numberValue: Float32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalFloat(number: Optional.bridgeJSLiftParameter(numberIsSome, numberValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalDouble") +@_cdecl("bjs_roundTripOptionalDouble") +public func _bjs_roundTripOptionalDouble(_ precisionIsSome: Int32, _ precisionValue: Float64) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalDouble(precision: Optional.bridgeJSLiftParameter(precisionIsSome, precisionValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalSyntax") +@_cdecl("bjs_roundTripOptionalSyntax") +public func _bjs_roundTripOptionalSyntax(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalSyntax(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalMixSyntax") +@_cdecl("bjs_roundTripOptionalMixSyntax") +public func _bjs_roundTripOptionalMixSyntax(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalMixSyntax(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalSwiftSyntax") +@_cdecl("bjs_roundTripOptionalSwiftSyntax") +public func _bjs_roundTripOptionalSwiftSyntax(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalSwiftSyntax(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalWithSpaces") +@_cdecl("bjs_roundTripOptionalWithSpaces") +public func _bjs_roundTripOptionalWithSpaces(_ valueIsSome: Int32, _ valueValue: Float64) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalWithSpaces(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalTypeAlias") +@_cdecl("bjs_roundTripOptionalTypeAlias") +public func _bjs_roundTripOptionalTypeAlias(_ ageIsSome: Int32, _ ageValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTypeAlias(age: Optional.bridgeJSLiftParameter(ageIsSome, ageValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalStatus") +@_cdecl("bjs_roundTripOptionalStatus") +public func _bjs_roundTripOptionalStatus(_ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalStatus(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalTheme") +@_cdecl("bjs_roundTripOptionalTheme") +public func _bjs_roundTripOptionalTheme(_ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTheme(value: Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalHttpStatus") +@_cdecl("bjs_roundTripOptionalHttpStatus") +public func _bjs_roundTripOptionalHttpStatus(_ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalHttpStatus(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalTSDirection") +@_cdecl("bjs_roundTripOptionalTSDirection") +public func _bjs_roundTripOptionalTSDirection(_ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTSDirection(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalTSTheme") +@_cdecl("bjs_roundTripOptionalTSTheme") +public func _bjs_roundTripOptionalTSTheme(_ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTSTheme(value: Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalNetworkingAPIMethod") +@_cdecl("bjs_roundTripOptionalNetworkingAPIMethod") +public func _bjs_roundTripOptionalNetworkingAPIMethod(_ methodIsSome: Int32, _ methodValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalNetworkingAPIMethod(_: Optional.bridgeJSLiftParameter(methodIsSome, methodValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalAPIResult") +@_cdecl("bjs_roundTripOptionalAPIResult") +public func _bjs_roundTripOptionalAPIResult(_ valueIsSome: Int32, _ valueCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalAPIResult(value: Optional.bridgeJSLiftParameter(valueIsSome, valueCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalTypedPayloadResult") +@_cdecl("bjs_roundTripOptionalTypedPayloadResult") +public func _bjs_roundTripOptionalTypedPayloadResult(_ resultIsSome: Int32, _ resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTypedPayloadResult(_: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_takeOptionalJSObject") +@_cdecl("bjs_takeOptionalJSObject") +public func _bjs_takeOptionalJSObject(_ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + takeOptionalJSObject(_: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_compareAPIResults") +@_cdecl("bjs_compareAPIResults") +public func _bjs_compareAPIResults(_ r1IsSome: Int32, _ r1CaseId: Int32, _ r2IsSome: Int32, _ r2CaseId: Int32) -> Void { + #if arch(wasm32) + let _tmp_r2 = Optional.bridgeJSLiftParameter(r2IsSome, r2CaseId) + let _tmp_r1 = Optional.bridgeJSLiftParameter(r1IsSome, r1CaseId) + let ret = compareAPIResults(_: _tmp_r1, _: _tmp_r2) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalComplexResult") +@_cdecl("bjs_roundTripOptionalComplexResult") +public func _bjs_roundTripOptionalComplexResult(_ resultIsSome: Int32, _ resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalComplexResult(_: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalAllTypesResult") +@_cdecl("bjs_roundTripOptionalAllTypesResult") +public func _bjs_roundTripOptionalAllTypesResult(_ resultIsSome: Int32, _ resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalAllTypesResult(_: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalPayloadResult") +@_cdecl("bjs_roundTripOptionalPayloadResult") +public func _bjs_roundTripOptionalPayloadResult(_ result: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalPayloadResult(_: OptionalAllTypesResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalPayloadResultOpt") +@_cdecl("bjs_roundTripOptionalPayloadResultOpt") +public func _bjs_roundTripOptionalPayloadResultOpt(_ resultIsSome: Int32, _ resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalPayloadResultOpt(_: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalClass") +@_cdecl("bjs_roundTripOptionalClass") +public func _bjs_roundTripOptionalClass(_ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalClass(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalGreeter") +@_cdecl("bjs_roundTripOptionalGreeter") +public func _bjs_roundTripOptionalGreeter(_ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalGreeter(_: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_applyOptionalGreeter") +@_cdecl("bjs_applyOptionalGreeter") +public func _bjs_applyOptionalGreeter(_ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer, _ transform: Int32) -> Void { + #if arch(wasm32) + let ret = applyOptionalGreeter(_: Optional.bridgeJSLiftParameter(valueIsSome, valueValue), _: _BJS_Closure_20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC.bridgeJSLift(transform)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeOptionalHolder") +@_cdecl("bjs_makeOptionalHolder") +public func _bjs_makeOptionalHolder(_ nullableGreeterIsSome: Int32, _ nullableGreeterValue: UnsafeMutableRawPointer, _ undefinedNumberIsSome: Int32, _ undefinedNumberValue: Float64) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = makeOptionalHolder(nullableGreeter: Optional.bridgeJSLiftParameter(nullableGreeterIsSome, nullableGreeterValue), undefinedNumber: JSUndefinedOr.bridgeJSLiftParameter(undefinedNumberIsSome, undefinedNumberValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalAPIOptionalResult") +@_cdecl("bjs_roundTripOptionalAPIOptionalResult") +public func _bjs_roundTripOptionalAPIOptionalResult(_ resultIsSome: Int32, _ resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalAPIOptionalResult(result: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + 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 +} + +@_expose(wasm, "bjs_testStructDefault") +@_cdecl("bjs_testStructDefault") +public func _bjs_testStructDefault() -> Void { + #if arch(wasm32) + let ret = testStructDefault(point: DataPoint.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_cartToJSObject") +@_cdecl("bjs_cartToJSObject") +public func _bjs_cartToJSObject() -> Int32 { + #if arch(wasm32) + let ret = cartToJSObject(_: CopyableCart.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_nestedCartToJSObject") +@_cdecl("bjs_nestedCartToJSObject") +public func _bjs_nestedCartToJSObject() -> Int32 { + #if arch(wasm32) + let ret = nestedCartToJSObject(_: CopyableNestedCart.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripDataPoint") +@_cdecl("bjs_roundTripDataPoint") +public func _bjs_roundTripDataPoint() -> Void { + #if arch(wasm32) + let ret = roundTripDataPoint(_: DataPoint.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripPublicPoint") +@_cdecl("bjs_roundTripPublicPoint") +public func _bjs_roundTripPublicPoint() -> Void { + #if arch(wasm32) + let ret = roundTripPublicPoint(_: PublicPoint.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripContact") +@_cdecl("bjs_roundTripContact") +public func _bjs_roundTripContact() -> Void { + #if arch(wasm32) + let ret = roundTripContact(_: Contact.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripConfig") +@_cdecl("bjs_roundTripConfig") +public func _bjs_roundTripConfig() -> Void { + #if arch(wasm32) + let ret = roundTripConfig(_: Config.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripSessionData") +@_cdecl("bjs_roundTripSessionData") +public func _bjs_roundTripSessionData() -> Void { + #if arch(wasm32) + let ret = roundTripSessionData(_: SessionData.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripValidationReport") +@_cdecl("bjs_roundTripValidationReport") +public func _bjs_roundTripValidationReport() -> Void { + #if arch(wasm32) + let ret = roundTripValidationReport(_: ValidationReport.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #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 { + #if arch(wasm32) + let _tmp_report = ValidationReport.bridgeJSLiftParameter() + let _tmp_newResult = Optional.bridgeJSLiftParameter(newResultIsSome, newResultCaseId) + let ret = updateValidationReport(_: _tmp_newResult, _: _tmp_report) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testContainerWithStruct") +@_cdecl("bjs_testContainerWithStruct") +public func _bjs_testContainerWithStruct() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = testContainerWithStruct(_: DataPoint.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripJSObjectContainer") +@_cdecl("bjs_roundTripJSObjectContainer") +public func _bjs_roundTripJSObjectContainer() -> Void { + #if arch(wasm32) + let ret = roundTripJSObjectContainer(_: JSObjectContainer.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripFooContainer") +@_cdecl("bjs_roundTripFooContainer") +public func _bjs_roundTripFooContainer() -> Void { + #if arch(wasm32) + let ret = roundTripFooContainer(_: FooContainer.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripArrayMembers") +@_cdecl("bjs_roundTripArrayMembers") +public func _bjs_roundTripArrayMembers() -> Void { + #if arch(wasm32) + let ret = roundTripArrayMembers(_: ArrayMembers.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_arrayMembersSum") +@_cdecl("bjs_arrayMembersSum") +public func _bjs_arrayMembersSum() -> Int32 { + #if arch(wasm32) + let _tmp_values = [Int].bridgeJSStackPop() + let _tmp_value = ArrayMembers.bridgeJSLiftParameter() + let ret = arrayMembersSum(_: _tmp_value, _: _tmp_values) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_arrayMembersFirst") +@_cdecl("bjs_arrayMembersFirst") +public func _bjs_arrayMembersFirst() -> Void { + #if arch(wasm32) + let _tmp_values = [String].bridgeJSStackPop() + let _tmp_value = ArrayMembers.bridgeJSLiftParameter() + let ret = arrayMembersFirst(_: _tmp_value, _: _tmp_values) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClosureSupportExports_static_makeIntToInt") +@_cdecl("bjs_ClosureSupportExports_static_makeIntToInt") +public func _bjs_ClosureSupportExports_static_makeIntToInt(_ base: Int32) -> Int32 { + #if arch(wasm32) + let ret = ClosureSupportExports.makeIntToInt(_: Int.bridgeJSLiftParameter(base)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClosureSupportExports_static_makeDoubleToDouble") +@_cdecl("bjs_ClosureSupportExports_static_makeDoubleToDouble") +public func _bjs_ClosureSupportExports_static_makeDoubleToDouble(_ base: Float64) -> Int32 { + #if arch(wasm32) + let ret = ClosureSupportExports.makeDoubleToDouble(_: Double.bridgeJSLiftParameter(base)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClosureSupportExports_static_makeStringToString") +@_cdecl("bjs_ClosureSupportExports_static_makeStringToString") +public func _bjs_ClosureSupportExports_static_makeStringToString(_ prefixBytes: Int32, _ prefixLength: Int32) -> Int32 { + #if arch(wasm32) + let ret = ClosureSupportExports.makeStringToString(_: String.bridgeJSLiftParameter(prefixBytes, prefixLength)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClosureSupportExports_static_makeJSIntToInt") +@_cdecl("bjs_ClosureSupportExports_static_makeJSIntToInt") +public func _bjs_ClosureSupportExports_static_makeJSIntToInt(_ base: Int32) -> Int32 { + #if arch(wasm32) + let ret = ClosureSupportExports.makeJSIntToInt(_: Int.bridgeJSLiftParameter(base)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClosureSupportExports_static_makeJSDoubleToDouble") +@_cdecl("bjs_ClosureSupportExports_static_makeJSDoubleToDouble") +public func _bjs_ClosureSupportExports_static_makeJSDoubleToDouble(_ base: Float64) -> Int32 { + #if arch(wasm32) + let ret = ClosureSupportExports.makeJSDoubleToDouble(_: Double.bridgeJSLiftParameter(base)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClosureSupportExports_static_makeJSStringToString") +@_cdecl("bjs_ClosureSupportExports_static_makeJSStringToString") +public func _bjs_ClosureSupportExports_static_makeJSStringToString(_ prefixBytes: Int32, _ prefixLength: Int32) -> Int32 { + #if arch(wasm32) + let ret = ClosureSupportExports.makeJSStringToString(_: String.bridgeJSLiftParameter(prefixBytes, prefixLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ClosureSupportExports_deinit") +@_cdecl("bjs_ClosureSupportExports_deinit") +public func _bjs_ClosureSupportExports_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension ClosureSupportExports: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_ClosureSupportExports_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportExports_wrap") +fileprivate func _bjs_ClosureSupportExports_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_ClosureSupportExports_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_Greeter_init") +@_cdecl("bjs_Greeter_init") +public func _bjs_Greeter_init(_ nameBytes: Int32, _ nameLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Greeter(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_greet") +@_cdecl("bjs_Greeter_greet") +public func _bjs_Greeter_greet(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Greeter.bridgeJSLiftParameter(_self).greet() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_changeName") +@_cdecl("bjs_Greeter_changeName") +public func _bjs_Greeter_changeName(_ _self: UnsafeMutableRawPointer, _ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + Greeter.bridgeJSLiftParameter(_self).changeName(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_greetWith") +@_cdecl("bjs_Greeter_greetWith") +public func _bjs_Greeter_greetWith(_ _self: UnsafeMutableRawPointer, _ greeter: UnsafeMutableRawPointer, _ customGreeting: Int32) -> Void { + #if arch(wasm32) + let ret = Greeter.bridgeJSLiftParameter(_self).greetWith(greeter: Greeter.bridgeJSLiftParameter(greeter), customGreeting: _BJS_Closure_20BridgeJSRuntimeTests7GreeterC_SS.bridgeJSLift(customGreeting)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_makeFormatter") +@_cdecl("bjs_Greeter_makeFormatter") +public func _bjs_Greeter_makeFormatter(_ _self: UnsafeMutableRawPointer, _ suffixBytes: Int32, _ suffixLength: Int32) -> Int32 { + #if arch(wasm32) + let ret = Greeter.bridgeJSLiftParameter(_self).makeFormatter(suffix: String.bridgeJSLiftParameter(suffixBytes, suffixLength)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_static_makeCreator") +@_cdecl("bjs_Greeter_static_makeCreator") +public func _bjs_Greeter_static_makeCreator(_ defaultNameBytes: Int32, _ defaultNameLength: Int32) -> Int32 { + #if arch(wasm32) + let ret = Greeter.makeCreator(defaultName: String.bridgeJSLiftParameter(defaultNameBytes, defaultNameLength)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_makeCustomGreeter") +@_cdecl("bjs_Greeter_makeCustomGreeter") +public func _bjs_Greeter_makeCustomGreeter(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = Greeter.bridgeJSLiftParameter(_self).makeCustomGreeter() + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_name_get") +@_cdecl("bjs_Greeter_name_get") +public func _bjs_Greeter_name_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Greeter.bridgeJSLiftParameter(_self).name + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_name_set") +@_cdecl("bjs_Greeter_name_set") +public func _bjs_Greeter_name_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + Greeter.bridgeJSLiftParameter(_self).name = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_prefix_get") +@_cdecl("bjs_Greeter_prefix_get") +public func _bjs_Greeter_prefix_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Greeter.bridgeJSLiftParameter(_self).prefix + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_deinit") +@_cdecl("bjs_Greeter_deinit") +public func _bjs_Greeter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Greeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + public var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Greeter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Greeter_wrap") +fileprivate func _bjs_Greeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Greeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_Calculator_square") +@_cdecl("bjs_Calculator_square") +public func _bjs_Calculator_square(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Int32 { + #if arch(wasm32) + let ret = Calculator.bridgeJSLiftParameter(_self).square(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Calculator_add") +@_cdecl("bjs_Calculator_add") +public func _bjs_Calculator_add(_ _self: UnsafeMutableRawPointer, _ a: Int32, _ b: Int32) -> Int32 { + #if arch(wasm32) + let ret = Calculator.bridgeJSLiftParameter(_self).add(a: Int.bridgeJSLiftParameter(a), b: Int.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Calculator_deinit") +@_cdecl("bjs_Calculator_deinit") +public func _bjs_Calculator_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Calculator: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Calculator_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Calculator_wrap") +fileprivate func _bjs_Calculator_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Calculator_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_InternalGreeter_deinit") +@_cdecl("bjs_InternalGreeter_deinit") +public func _bjs_InternalGreeter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension InternalGreeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + internal var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_InternalGreeter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_InternalGreeter_wrap") +fileprivate func _bjs_InternalGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_InternalGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_PublicGreeter_deinit") +@_cdecl("bjs_PublicGreeter_deinit") +public func _bjs_PublicGreeter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension PublicGreeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + public var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_PublicGreeter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_PublicGreeter_wrap") +fileprivate func _bjs_PublicGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_PublicGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_PackageGreeter_deinit") +@_cdecl("bjs_PackageGreeter_deinit") +public func _bjs_PackageGreeter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension PackageGreeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + package var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_PackageGreeter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_PackageGreeter_wrap") +fileprivate func _bjs_PackageGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_PackageGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_Converter_init") +@_cdecl("bjs_Converter_init") +public func _bjs_Converter_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Utils.Converter() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Converter_toString") +@_cdecl("bjs_Converter_toString") +public func _bjs_Converter_toString(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + let ret = Utils.Converter.bridgeJSLiftParameter(_self).toString(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Converter_deinit") +@_cdecl("bjs_Converter_deinit") +public func _bjs_Converter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Utils.Converter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Converter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Converter_wrap") +fileprivate func _bjs_Converter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Converter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_HTTPServer_init") +@_cdecl("bjs_HTTPServer_init") +public func _bjs_HTTPServer_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Networking.API.HTTPServer() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_HTTPServer_call") +@_cdecl("bjs_HTTPServer_call") +public func _bjs_HTTPServer_call(_ _self: UnsafeMutableRawPointer, _ method: Int32) -> Void { + #if arch(wasm32) + Networking.API.HTTPServer.bridgeJSLiftParameter(_self).call(_: Networking.API.Method.bridgeJSLiftParameter(method)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_HTTPServer_deinit") +@_cdecl("bjs_HTTPServer_deinit") +public func _bjs_HTTPServer_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Networking.API.HTTPServer: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_HTTPServer_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_HTTPServer_wrap") +fileprivate func _bjs_HTTPServer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_HTTPServer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_TestServer_init") +@_cdecl("bjs_TestServer_init") +public func _bjs_TestServer_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Internal.TestServer() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TestServer_call") +@_cdecl("bjs_TestServer_call") +public func _bjs_TestServer_call(_ _self: UnsafeMutableRawPointer, _ method: Int32) -> Void { + #if arch(wasm32) + Internal.TestServer.bridgeJSLiftParameter(_self).call(_: Internal.SupportedMethod.bridgeJSLiftParameter(method)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TestServer_deinit") +@_cdecl("bjs_TestServer_deinit") +public func _bjs_TestServer_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Internal.TestServer: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_TestServer_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_TestServer_wrap") +fileprivate func _bjs_TestServer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_TestServer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_SimplePropertyHolder_init") +@_cdecl("bjs_SimplePropertyHolder_init") +public func _bjs_SimplePropertyHolder_init(_ value: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = SimplePropertyHolder(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SimplePropertyHolder_value_get") +@_cdecl("bjs_SimplePropertyHolder_value_get") +public func _bjs_SimplePropertyHolder_value_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = SimplePropertyHolder.bridgeJSLiftParameter(_self).value + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SimplePropertyHolder_value_set") +@_cdecl("bjs_SimplePropertyHolder_value_set") +public func _bjs_SimplePropertyHolder_value_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + SimplePropertyHolder.bridgeJSLiftParameter(_self).value = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SimplePropertyHolder_deinit") +@_cdecl("bjs_SimplePropertyHolder_deinit") +public func _bjs_SimplePropertyHolder_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension SimplePropertyHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_SimplePropertyHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_SimplePropertyHolder_wrap") +fileprivate func _bjs_SimplePropertyHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_SimplePropertyHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_PropertyHolder_init") +@_cdecl("bjs_PropertyHolder_init") +public func _bjs_PropertyHolder_init(_ intValue: Int32, _ floatValue: Float32, _ doubleValue: Float64, _ boolValue: Int32, _ stringValueBytes: Int32, _ stringValueLength: Int32, _ jsObject: Int32, _ sibling: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = PropertyHolder(intValue: Int.bridgeJSLiftParameter(intValue), floatValue: Float.bridgeJSLiftParameter(floatValue), doubleValue: Double.bridgeJSLiftParameter(doubleValue), boolValue: Bool.bridgeJSLiftParameter(boolValue), stringValue: String.bridgeJSLiftParameter(stringValueBytes, stringValueLength), jsObject: JSObject.bridgeJSLiftParameter(jsObject), sibling: SimplePropertyHolder.bridgeJSLiftParameter(sibling)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_getAllValues") +@_cdecl("bjs_PropertyHolder_getAllValues") +public func _bjs_PropertyHolder_getAllValues(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).getAllValues() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_intValue_get") +@_cdecl("bjs_PropertyHolder_intValue_get") +public func _bjs_PropertyHolder_intValue_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).intValue + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_intValue_set") +@_cdecl("bjs_PropertyHolder_intValue_set") +public func _bjs_PropertyHolder_intValue_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).intValue = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_floatValue_get") +@_cdecl("bjs_PropertyHolder_floatValue_get") +public func _bjs_PropertyHolder_floatValue_get(_ _self: UnsafeMutableRawPointer) -> Float32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).floatValue + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_floatValue_set") +@_cdecl("bjs_PropertyHolder_floatValue_set") +public func _bjs_PropertyHolder_floatValue_set(_ _self: UnsafeMutableRawPointer, _ value: Float32) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).floatValue = Float.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_doubleValue_get") +@_cdecl("bjs_PropertyHolder_doubleValue_get") +public func _bjs_PropertyHolder_doubleValue_get(_ _self: UnsafeMutableRawPointer) -> Float64 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).doubleValue + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_doubleValue_set") +@_cdecl("bjs_PropertyHolder_doubleValue_set") +public func _bjs_PropertyHolder_doubleValue_set(_ _self: UnsafeMutableRawPointer, _ value: Float64) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).doubleValue = Double.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_boolValue_get") +@_cdecl("bjs_PropertyHolder_boolValue_get") +public func _bjs_PropertyHolder_boolValue_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).boolValue + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_boolValue_set") +@_cdecl("bjs_PropertyHolder_boolValue_set") +public func _bjs_PropertyHolder_boolValue_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).boolValue = Bool.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_stringValue_get") +@_cdecl("bjs_PropertyHolder_stringValue_get") +public func _bjs_PropertyHolder_stringValue_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).stringValue + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_stringValue_set") +@_cdecl("bjs_PropertyHolder_stringValue_set") +public func _bjs_PropertyHolder_stringValue_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).stringValue = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_readonlyInt_get") +@_cdecl("bjs_PropertyHolder_readonlyInt_get") +public func _bjs_PropertyHolder_readonlyInt_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyInt + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_readonlyFloat_get") +@_cdecl("bjs_PropertyHolder_readonlyFloat_get") +public func _bjs_PropertyHolder_readonlyFloat_get(_ _self: UnsafeMutableRawPointer) -> Float32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyFloat + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_readonlyDouble_get") +@_cdecl("bjs_PropertyHolder_readonlyDouble_get") +public func _bjs_PropertyHolder_readonlyDouble_get(_ _self: UnsafeMutableRawPointer) -> Float64 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyDouble + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_readonlyBool_get") +@_cdecl("bjs_PropertyHolder_readonlyBool_get") +public func _bjs_PropertyHolder_readonlyBool_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyBool + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_readonlyString_get") +@_cdecl("bjs_PropertyHolder_readonlyString_get") +public func _bjs_PropertyHolder_readonlyString_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).readonlyString + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_jsObject_get") +@_cdecl("bjs_PropertyHolder_jsObject_get") +public func _bjs_PropertyHolder_jsObject_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).jsObject + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_jsObject_set") +@_cdecl("bjs_PropertyHolder_jsObject_set") +public func _bjs_PropertyHolder_jsObject_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).jsObject = JSObject.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_sibling_get") +@_cdecl("bjs_PropertyHolder_sibling_get") +public func _bjs_PropertyHolder_sibling_get(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).sibling + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_sibling_set") +@_cdecl("bjs_PropertyHolder_sibling_set") +public func _bjs_PropertyHolder_sibling_set(_ _self: UnsafeMutableRawPointer, _ value: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).sibling = SimplePropertyHolder.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_lazyValue_get") +@_cdecl("bjs_PropertyHolder_lazyValue_get") +public func _bjs_PropertyHolder_lazyValue_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).lazyValue + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_lazyValue_set") +@_cdecl("bjs_PropertyHolder_lazyValue_set") +public func _bjs_PropertyHolder_lazyValue_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).lazyValue = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_computedReadonly_get") +@_cdecl("bjs_PropertyHolder_computedReadonly_get") +public func _bjs_PropertyHolder_computedReadonly_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).computedReadonly + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_computedReadWrite_get") +@_cdecl("bjs_PropertyHolder_computedReadWrite_get") +public func _bjs_PropertyHolder_computedReadWrite_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).computedReadWrite + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_computedReadWrite_set") +@_cdecl("bjs_PropertyHolder_computedReadWrite_set") +public func _bjs_PropertyHolder_computedReadWrite_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).computedReadWrite = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_observedProperty_get") +@_cdecl("bjs_PropertyHolder_observedProperty_get") +public func _bjs_PropertyHolder_observedProperty_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = PropertyHolder.bridgeJSLiftParameter(_self).observedProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_observedProperty_set") +@_cdecl("bjs_PropertyHolder_observedProperty_set") +public func _bjs_PropertyHolder_observedProperty_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + PropertyHolder.bridgeJSLiftParameter(_self).observedProperty = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyHolder_deinit") +@_cdecl("bjs_PropertyHolder_deinit") +public func _bjs_PropertyHolder_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension PropertyHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_PropertyHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_PropertyHolder_wrap") +fileprivate func _bjs_PropertyHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_PropertyHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_MathUtils_static_add") +@_cdecl("bjs_MathUtils_static_add") +public func _bjs_MathUtils_static_add(_ a: Int32, _ b: Int32) -> Int32 { + #if arch(wasm32) + let ret = MathUtils.add(a: Int.bridgeJSLiftParameter(a), b: Int.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_static_substract") +@_cdecl("bjs_MathUtils_static_substract") +public func _bjs_MathUtils_static_substract(_ a: Int32, _ b: Int32) -> Int32 { + #if arch(wasm32) + let ret = MathUtils.substract(a: Int.bridgeJSLiftParameter(a), b: Int.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_deinit") +@_cdecl("bjs_MathUtils_deinit") +public func _bjs_MathUtils_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension MathUtils: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_MathUtils_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_MathUtils_wrap") +fileprivate func _bjs_MathUtils_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_MathUtils_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_ConstructorDefaults_init") +@_cdecl("bjs_ConstructorDefaults_init") +public func _bjs_ConstructorDefaults_init(_ nameBytes: Int32, _ nameLength: Int32, _ count: Int32, _ enabled: Int32, _ status: Int32, _ tagIsSome: Int32, _ tagBytes: Int32, _ tagLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = ConstructorDefaults(name: String.bridgeJSLiftParameter(nameBytes, nameLength), count: Int.bridgeJSLiftParameter(count), enabled: Bool.bridgeJSLiftParameter(enabled), status: Status.bridgeJSLiftParameter(status), tag: Optional.bridgeJSLiftParameter(tagIsSome, tagBytes, tagLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_describe") +@_cdecl("bjs_ConstructorDefaults_describe") +public func _bjs_ConstructorDefaults_describe(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ConstructorDefaults.bridgeJSLiftParameter(_self).describe() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_name_get") +@_cdecl("bjs_ConstructorDefaults_name_get") +public func _bjs_ConstructorDefaults_name_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ConstructorDefaults.bridgeJSLiftParameter(_self).name + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_name_set") +@_cdecl("bjs_ConstructorDefaults_name_set") +public func _bjs_ConstructorDefaults_name_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + ConstructorDefaults.bridgeJSLiftParameter(_self).name = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_count_get") +@_cdecl("bjs_ConstructorDefaults_count_get") +public func _bjs_ConstructorDefaults_count_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = ConstructorDefaults.bridgeJSLiftParameter(_self).count + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_count_set") +@_cdecl("bjs_ConstructorDefaults_count_set") +public func _bjs_ConstructorDefaults_count_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + ConstructorDefaults.bridgeJSLiftParameter(_self).count = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_enabled_get") +@_cdecl("bjs_ConstructorDefaults_enabled_get") +public func _bjs_ConstructorDefaults_enabled_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = ConstructorDefaults.bridgeJSLiftParameter(_self).enabled + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_enabled_set") +@_cdecl("bjs_ConstructorDefaults_enabled_set") +public func _bjs_ConstructorDefaults_enabled_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + ConstructorDefaults.bridgeJSLiftParameter(_self).enabled = Bool.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_status_get") +@_cdecl("bjs_ConstructorDefaults_status_get") +public func _bjs_ConstructorDefaults_status_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = ConstructorDefaults.bridgeJSLiftParameter(_self).status + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_status_set") +@_cdecl("bjs_ConstructorDefaults_status_set") +public func _bjs_ConstructorDefaults_status_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + ConstructorDefaults.bridgeJSLiftParameter(_self).status = Status.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_tag_get") +@_cdecl("bjs_ConstructorDefaults_tag_get") +public func _bjs_ConstructorDefaults_tag_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ConstructorDefaults.bridgeJSLiftParameter(_self).tag + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_tag_set") +@_cdecl("bjs_ConstructorDefaults_tag_set") +public func _bjs_ConstructorDefaults_tag_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + ConstructorDefaults.bridgeJSLiftParameter(_self).tag = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ConstructorDefaults_deinit") +@_cdecl("bjs_ConstructorDefaults_deinit") +public func _bjs_ConstructorDefaults_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension ConstructorDefaults: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_ConstructorDefaults_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ConstructorDefaults_wrap") +fileprivate func _bjs_ConstructorDefaults_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_ConstructorDefaults_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_StaticPropertyHolder_init") +@_cdecl("bjs_StaticPropertyHolder_init") +public func _bjs_StaticPropertyHolder_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = StaticPropertyHolder() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticConstant_get") +@_cdecl("bjs_StaticPropertyHolder_static_staticConstant_get") +public func _bjs_StaticPropertyHolder_static_staticConstant_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyHolder.staticConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticVariable_get") +@_cdecl("bjs_StaticPropertyHolder_static_staticVariable_get") +public func _bjs_StaticPropertyHolder_static_staticVariable_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyHolder.staticVariable + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticVariable_set") +@_cdecl("bjs_StaticPropertyHolder_static_staticVariable_set") +public func _bjs_StaticPropertyHolder_static_staticVariable_set(_ value: Int32) -> Void { + #if arch(wasm32) + StaticPropertyHolder.staticVariable = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticString_get") +@_cdecl("bjs_StaticPropertyHolder_static_staticString_get") +public func _bjs_StaticPropertyHolder_static_staticString_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyHolder.staticString + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticString_set") +@_cdecl("bjs_StaticPropertyHolder_static_staticString_set") +public func _bjs_StaticPropertyHolder_static_staticString_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + StaticPropertyHolder.staticString = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticBool_get") +@_cdecl("bjs_StaticPropertyHolder_static_staticBool_get") +public func _bjs_StaticPropertyHolder_static_staticBool_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyHolder.staticBool + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticBool_set") +@_cdecl("bjs_StaticPropertyHolder_static_staticBool_set") +public func _bjs_StaticPropertyHolder_static_staticBool_set(_ value: Int32) -> Void { + #if arch(wasm32) + StaticPropertyHolder.staticBool = Bool.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticFloat_get") +@_cdecl("bjs_StaticPropertyHolder_static_staticFloat_get") +public func _bjs_StaticPropertyHolder_static_staticFloat_get() -> Float32 { + #if arch(wasm32) + let ret = StaticPropertyHolder.staticFloat + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticFloat_set") +@_cdecl("bjs_StaticPropertyHolder_static_staticFloat_set") +public func _bjs_StaticPropertyHolder_static_staticFloat_set(_ value: Float32) -> Void { + #if arch(wasm32) + StaticPropertyHolder.staticFloat = Float.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticDouble_get") +@_cdecl("bjs_StaticPropertyHolder_static_staticDouble_get") +public func _bjs_StaticPropertyHolder_static_staticDouble_get() -> Float64 { + #if arch(wasm32) + let ret = StaticPropertyHolder.staticDouble + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticDouble_set") +@_cdecl("bjs_StaticPropertyHolder_static_staticDouble_set") +public func _bjs_StaticPropertyHolder_static_staticDouble_set(_ value: Float64) -> Void { + #if arch(wasm32) + StaticPropertyHolder.staticDouble = Double.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_computedProperty_get") +@_cdecl("bjs_StaticPropertyHolder_static_computedProperty_get") +public func _bjs_StaticPropertyHolder_static_computedProperty_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyHolder.computedProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_computedProperty_set") +@_cdecl("bjs_StaticPropertyHolder_static_computedProperty_set") +public func _bjs_StaticPropertyHolder_static_computedProperty_set(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + StaticPropertyHolder.computedProperty = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_readOnlyComputed_get") +@_cdecl("bjs_StaticPropertyHolder_static_readOnlyComputed_get") +public func _bjs_StaticPropertyHolder_static_readOnlyComputed_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyHolder.readOnlyComputed + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_optionalString_get") +@_cdecl("bjs_StaticPropertyHolder_static_optionalString_get") +public func _bjs_StaticPropertyHolder_static_optionalString_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyHolder.optionalString + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_optionalString_set") +@_cdecl("bjs_StaticPropertyHolder_static_optionalString_set") +public func _bjs_StaticPropertyHolder_static_optionalString_set(_ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + StaticPropertyHolder.optionalString = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_optionalInt_get") +@_cdecl("bjs_StaticPropertyHolder_static_optionalInt_get") +public func _bjs_StaticPropertyHolder_static_optionalInt_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyHolder.optionalInt + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_optionalInt_set") +@_cdecl("bjs_StaticPropertyHolder_static_optionalInt_set") +public func _bjs_StaticPropertyHolder_static_optionalInt_set(_ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + StaticPropertyHolder.optionalInt = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_jsObjectProperty_get") +@_cdecl("bjs_StaticPropertyHolder_static_jsObjectProperty_get") +public func _bjs_StaticPropertyHolder_static_jsObjectProperty_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyHolder.jsObjectProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_jsObjectProperty_set") +@_cdecl("bjs_StaticPropertyHolder_static_jsObjectProperty_set") +public func _bjs_StaticPropertyHolder_static_jsObjectProperty_set(_ value: Int32) -> Void { + #if arch(wasm32) + StaticPropertyHolder.jsObjectProperty = JSObject.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_deinit") +@_cdecl("bjs_StaticPropertyHolder_deinit") +public func _bjs_StaticPropertyHolder_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension StaticPropertyHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_StaticPropertyHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_StaticPropertyHolder_wrap") +fileprivate func _bjs_StaticPropertyHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_StaticPropertyHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_DataProcessorManager_init") +@_cdecl("bjs_DataProcessorManager_init") +public func _bjs_DataProcessorManager_init(_ processor: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = DataProcessorManager(processor: AnyDataProcessor.bridgeJSLiftParameter(processor)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_incrementByAmount") +@_cdecl("bjs_DataProcessorManager_incrementByAmount") +public func _bjs_DataProcessorManager_incrementByAmount(_ _self: UnsafeMutableRawPointer, _ amount: Int32) -> Void { + #if arch(wasm32) + DataProcessorManager.bridgeJSLiftParameter(_self).incrementByAmount(_: Int.bridgeJSLiftParameter(amount)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_setProcessorLabel") +@_cdecl("bjs_DataProcessorManager_setProcessorLabel") +public func _bjs_DataProcessorManager_setProcessorLabel(_ _self: UnsafeMutableRawPointer, _ prefixBytes: Int32, _ prefixLength: Int32, _ suffixBytes: Int32, _ suffixLength: Int32) -> Void { + #if arch(wasm32) + DataProcessorManager.bridgeJSLiftParameter(_self).setProcessorLabel(_: String.bridgeJSLiftParameter(prefixBytes, prefixLength), _: String.bridgeJSLiftParameter(suffixBytes, suffixLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_isProcessorEven") +@_cdecl("bjs_DataProcessorManager_isProcessorEven") +public func _bjs_DataProcessorManager_isProcessorEven(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = DataProcessorManager.bridgeJSLiftParameter(_self).isProcessorEven() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_getProcessorLabel") +@_cdecl("bjs_DataProcessorManager_getProcessorLabel") +public func _bjs_DataProcessorManager_getProcessorLabel(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = DataProcessorManager.bridgeJSLiftParameter(_self).getProcessorLabel() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_getCurrentValue") +@_cdecl("bjs_DataProcessorManager_getCurrentValue") +public func _bjs_DataProcessorManager_getCurrentValue(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = DataProcessorManager.bridgeJSLiftParameter(_self).getCurrentValue() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_incrementBoth") +@_cdecl("bjs_DataProcessorManager_incrementBoth") +public func _bjs_DataProcessorManager_incrementBoth(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + DataProcessorManager.bridgeJSLiftParameter(_self).incrementBoth() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_getBackupValue") +@_cdecl("bjs_DataProcessorManager_getBackupValue") +public func _bjs_DataProcessorManager_getBackupValue(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = DataProcessorManager.bridgeJSLiftParameter(_self).getBackupValue() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_hasBackup") +@_cdecl("bjs_DataProcessorManager_hasBackup") +public func _bjs_DataProcessorManager_hasBackup(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = DataProcessorManager.bridgeJSLiftParameter(_self).hasBackup() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_getProcessorOptionalTag") +@_cdecl("bjs_DataProcessorManager_getProcessorOptionalTag") +public func _bjs_DataProcessorManager_getProcessorOptionalTag(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = DataProcessorManager.bridgeJSLiftParameter(_self).getProcessorOptionalTag() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_setProcessorOptionalTag") +@_cdecl("bjs_DataProcessorManager_setProcessorOptionalTag") +public func _bjs_DataProcessorManager_setProcessorOptionalTag(_ _self: UnsafeMutableRawPointer, _ tagIsSome: Int32, _ tagBytes: Int32, _ tagLength: Int32) -> Void { + #if arch(wasm32) + DataProcessorManager.bridgeJSLiftParameter(_self).setProcessorOptionalTag(_: Optional.bridgeJSLiftParameter(tagIsSome, tagBytes, tagLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_getProcessorOptionalCount") +@_cdecl("bjs_DataProcessorManager_getProcessorOptionalCount") +public func _bjs_DataProcessorManager_getProcessorOptionalCount(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = DataProcessorManager.bridgeJSLiftParameter(_self).getProcessorOptionalCount() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_setProcessorOptionalCount") +@_cdecl("bjs_DataProcessorManager_setProcessorOptionalCount") +public func _bjs_DataProcessorManager_setProcessorOptionalCount(_ _self: UnsafeMutableRawPointer, _ countIsSome: Int32, _ countValue: Int32) -> Void { + #if arch(wasm32) + DataProcessorManager.bridgeJSLiftParameter(_self).setProcessorOptionalCount(_: Optional.bridgeJSLiftParameter(countIsSome, countValue)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_getProcessorDirection") +@_cdecl("bjs_DataProcessorManager_getProcessorDirection") +public func _bjs_DataProcessorManager_getProcessorDirection(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = DataProcessorManager.bridgeJSLiftParameter(_self).getProcessorDirection() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_setProcessorDirection") +@_cdecl("bjs_DataProcessorManager_setProcessorDirection") +public func _bjs_DataProcessorManager_setProcessorDirection(_ _self: UnsafeMutableRawPointer, _ directionIsSome: Int32, _ directionValue: Int32) -> Void { + #if arch(wasm32) + DataProcessorManager.bridgeJSLiftParameter(_self).setProcessorDirection(_: Optional.bridgeJSLiftParameter(directionIsSome, directionValue)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_getProcessorTheme") +@_cdecl("bjs_DataProcessorManager_getProcessorTheme") +public func _bjs_DataProcessorManager_getProcessorTheme(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = DataProcessorManager.bridgeJSLiftParameter(_self).getProcessorTheme() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_setProcessorTheme") +@_cdecl("bjs_DataProcessorManager_setProcessorTheme") +public func _bjs_DataProcessorManager_setProcessorTheme(_ _self: UnsafeMutableRawPointer, _ themeIsSome: Int32, _ themeBytes: Int32, _ themeLength: Int32) -> Void { + #if arch(wasm32) + DataProcessorManager.bridgeJSLiftParameter(_self).setProcessorTheme(_: Optional.bridgeJSLiftParameter(themeIsSome, themeBytes, themeLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_getProcessorHttpStatus") +@_cdecl("bjs_DataProcessorManager_getProcessorHttpStatus") +public func _bjs_DataProcessorManager_getProcessorHttpStatus(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = DataProcessorManager.bridgeJSLiftParameter(_self).getProcessorHttpStatus() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_setProcessorHttpStatus") +@_cdecl("bjs_DataProcessorManager_setProcessorHttpStatus") +public func _bjs_DataProcessorManager_setProcessorHttpStatus(_ _self: UnsafeMutableRawPointer, _ statusIsSome: Int32, _ statusValue: Int32) -> Void { + #if arch(wasm32) + DataProcessorManager.bridgeJSLiftParameter(_self).setProcessorHttpStatus(_: Optional.bridgeJSLiftParameter(statusIsSome, statusValue)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_getProcessorAPIResult") +@_cdecl("bjs_DataProcessorManager_getProcessorAPIResult") +public func _bjs_DataProcessorManager_getProcessorAPIResult(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = DataProcessorManager.bridgeJSLiftParameter(_self).getProcessorAPIResult() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_setProcessorAPIResult") +@_cdecl("bjs_DataProcessorManager_setProcessorAPIResult") +public func _bjs_DataProcessorManager_setProcessorAPIResult(_ _self: UnsafeMutableRawPointer, _ apiResultIsSome: Int32, _ apiResultCaseId: Int32) -> Void { + #if arch(wasm32) + DataProcessorManager.bridgeJSLiftParameter(_self).setProcessorAPIResult(_: Optional.bridgeJSLiftParameter(apiResultIsSome, apiResultCaseId)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_processor_get") +@_cdecl("bjs_DataProcessorManager_processor_get") +public func _bjs_DataProcessorManager_processor_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = DataProcessorManager.bridgeJSLiftParameter(_self).processor as! AnyDataProcessor + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_processor_set") +@_cdecl("bjs_DataProcessorManager_processor_set") +public func _bjs_DataProcessorManager_processor_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + DataProcessorManager.bridgeJSLiftParameter(_self).processor = AnyDataProcessor.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_backupProcessor_get") +@_cdecl("bjs_DataProcessorManager_backupProcessor_get") +public func _bjs_DataProcessorManager_backupProcessor_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = (DataProcessorManager.bridgeJSLiftParameter(_self).backupProcessor).flatMap { $0 as? AnyDataProcessor } + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_backupProcessor_set") +@_cdecl("bjs_DataProcessorManager_backupProcessor_set") +public func _bjs_DataProcessorManager_backupProcessor_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + DataProcessorManager.bridgeJSLiftParameter(_self).backupProcessor = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DataProcessorManager_deinit") +@_cdecl("bjs_DataProcessorManager_deinit") +public func _bjs_DataProcessorManager_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension DataProcessorManager: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_DataProcessorManager_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessorManager_wrap") +fileprivate func _bjs_DataProcessorManager_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_DataProcessorManager_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_SwiftDataProcessor_init") +@_cdecl("bjs_SwiftDataProcessor_init") +public func _bjs_SwiftDataProcessor_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = SwiftDataProcessor() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_increment") +@_cdecl("bjs_SwiftDataProcessor_increment") +public func _bjs_SwiftDataProcessor_increment(_ _self: UnsafeMutableRawPointer, _ amount: Int32) -> Void { + #if arch(wasm32) + SwiftDataProcessor.bridgeJSLiftParameter(_self).increment(by: Int.bridgeJSLiftParameter(amount)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_getValue") +@_cdecl("bjs_SwiftDataProcessor_getValue") +public func _bjs_SwiftDataProcessor_getValue(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).getValue() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_setLabelElements") +@_cdecl("bjs_SwiftDataProcessor_setLabelElements") +public func _bjs_SwiftDataProcessor_setLabelElements(_ _self: UnsafeMutableRawPointer, _ labelPrefixBytes: Int32, _ labelPrefixLength: Int32, _ labelSuffixBytes: Int32, _ labelSuffixLength: Int32) -> Void { + #if arch(wasm32) + SwiftDataProcessor.bridgeJSLiftParameter(_self).setLabelElements(_: String.bridgeJSLiftParameter(labelPrefixBytes, labelPrefixLength), _: String.bridgeJSLiftParameter(labelSuffixBytes, labelSuffixLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_getLabel") +@_cdecl("bjs_SwiftDataProcessor_getLabel") +public func _bjs_SwiftDataProcessor_getLabel(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).getLabel() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_isEven") +@_cdecl("bjs_SwiftDataProcessor_isEven") +public func _bjs_SwiftDataProcessor_isEven(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).isEven() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_processGreeter") +@_cdecl("bjs_SwiftDataProcessor_processGreeter") +public func _bjs_SwiftDataProcessor_processGreeter(_ _self: UnsafeMutableRawPointer, _ greeter: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).processGreeter(_: Greeter.bridgeJSLiftParameter(greeter)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_createGreeter") +@_cdecl("bjs_SwiftDataProcessor_createGreeter") +public func _bjs_SwiftDataProcessor_createGreeter(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).createGreeter() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_processOptionalGreeter") +@_cdecl("bjs_SwiftDataProcessor_processOptionalGreeter") +public func _bjs_SwiftDataProcessor_processOptionalGreeter(_ _self: UnsafeMutableRawPointer, _ greeterIsSome: Int32, _ greeterValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).processOptionalGreeter(_: Optional.bridgeJSLiftParameter(greeterIsSome, greeterValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_createOptionalGreeter") +@_cdecl("bjs_SwiftDataProcessor_createOptionalGreeter") +public func _bjs_SwiftDataProcessor_createOptionalGreeter(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).createOptionalGreeter() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_handleAPIResult") +@_cdecl("bjs_SwiftDataProcessor_handleAPIResult") +public func _bjs_SwiftDataProcessor_handleAPIResult(_ _self: UnsafeMutableRawPointer, _ resultIsSome: Int32, _ resultCaseId: Int32) -> Void { + #if arch(wasm32) + SwiftDataProcessor.bridgeJSLiftParameter(_self).handleAPIResult(_: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_getAPIResult") +@_cdecl("bjs_SwiftDataProcessor_getAPIResult") +public func _bjs_SwiftDataProcessor_getAPIResult(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).getAPIResult() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_count_get") +@_cdecl("bjs_SwiftDataProcessor_count_get") +public func _bjs_SwiftDataProcessor_count_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).count + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_count_set") +@_cdecl("bjs_SwiftDataProcessor_count_set") +public func _bjs_SwiftDataProcessor_count_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + SwiftDataProcessor.bridgeJSLiftParameter(_self).count = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_name_get") +@_cdecl("bjs_SwiftDataProcessor_name_get") +public func _bjs_SwiftDataProcessor_name_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).name + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_optionalTag_get") +@_cdecl("bjs_SwiftDataProcessor_optionalTag_get") +public func _bjs_SwiftDataProcessor_optionalTag_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).optionalTag + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_optionalTag_set") +@_cdecl("bjs_SwiftDataProcessor_optionalTag_set") +public func _bjs_SwiftDataProcessor_optionalTag_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + SwiftDataProcessor.bridgeJSLiftParameter(_self).optionalTag = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_optionalCount_get") +@_cdecl("bjs_SwiftDataProcessor_optionalCount_get") +public func _bjs_SwiftDataProcessor_optionalCount_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).optionalCount + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_optionalCount_set") +@_cdecl("bjs_SwiftDataProcessor_optionalCount_set") +public func _bjs_SwiftDataProcessor_optionalCount_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + SwiftDataProcessor.bridgeJSLiftParameter(_self).optionalCount = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_direction_get") +@_cdecl("bjs_SwiftDataProcessor_direction_get") +public func _bjs_SwiftDataProcessor_direction_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).direction + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_direction_set") +@_cdecl("bjs_SwiftDataProcessor_direction_set") +public func _bjs_SwiftDataProcessor_direction_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + SwiftDataProcessor.bridgeJSLiftParameter(_self).direction = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_optionalTheme_get") +@_cdecl("bjs_SwiftDataProcessor_optionalTheme_get") +public func _bjs_SwiftDataProcessor_optionalTheme_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).optionalTheme + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_optionalTheme_set") +@_cdecl("bjs_SwiftDataProcessor_optionalTheme_set") +public func _bjs_SwiftDataProcessor_optionalTheme_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + SwiftDataProcessor.bridgeJSLiftParameter(_self).optionalTheme = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_httpStatus_get") +@_cdecl("bjs_SwiftDataProcessor_httpStatus_get") +public func _bjs_SwiftDataProcessor_httpStatus_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).httpStatus + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_httpStatus_set") +@_cdecl("bjs_SwiftDataProcessor_httpStatus_set") +public func _bjs_SwiftDataProcessor_httpStatus_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + SwiftDataProcessor.bridgeJSLiftParameter(_self).httpStatus = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_apiResult_get") +@_cdecl("bjs_SwiftDataProcessor_apiResult_get") +public func _bjs_SwiftDataProcessor_apiResult_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).apiResult + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_apiResult_set") +@_cdecl("bjs_SwiftDataProcessor_apiResult_set") +public func _bjs_SwiftDataProcessor_apiResult_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueCaseId: Int32) -> Void { + #if arch(wasm32) + SwiftDataProcessor.bridgeJSLiftParameter(_self).apiResult = Optional.bridgeJSLiftParameter(valueIsSome, valueCaseId) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_helper_get") +@_cdecl("bjs_SwiftDataProcessor_helper_get") +public func _bjs_SwiftDataProcessor_helper_get(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).helper + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_helper_set") +@_cdecl("bjs_SwiftDataProcessor_helper_set") +public func _bjs_SwiftDataProcessor_helper_set(_ _self: UnsafeMutableRawPointer, _ value: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + SwiftDataProcessor.bridgeJSLiftParameter(_self).helper = Greeter.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_optionalHelper_get") +@_cdecl("bjs_SwiftDataProcessor_optionalHelper_get") +public func _bjs_SwiftDataProcessor_optionalHelper_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = SwiftDataProcessor.bridgeJSLiftParameter(_self).optionalHelper + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_optionalHelper_set") +@_cdecl("bjs_SwiftDataProcessor_optionalHelper_set") +public func _bjs_SwiftDataProcessor_optionalHelper_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + SwiftDataProcessor.bridgeJSLiftParameter(_self).optionalHelper = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_SwiftDataProcessor_deinit") +@_cdecl("bjs_SwiftDataProcessor_deinit") +public func _bjs_SwiftDataProcessor_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension SwiftDataProcessor: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_SwiftDataProcessor_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_SwiftDataProcessor_wrap") +fileprivate func _bjs_SwiftDataProcessor_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_SwiftDataProcessor_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_TextProcessor_init") +@_cdecl("bjs_TextProcessor_init") +public func _bjs_TextProcessor_init(_ transform: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = TextProcessor(transform: _BJS_Closure_20BridgeJSRuntimeTestsSS_SS.bridgeJSLift(transform)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_process") +@_cdecl("bjs_TextProcessor_process") +public func _bjs_TextProcessor_process(_ _self: UnsafeMutableRawPointer, _ textBytes: Int32, _ textLength: Int32) -> Void { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).process(_: String.bridgeJSLiftParameter(textBytes, textLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_processWithCustom") +@_cdecl("bjs_TextProcessor_processWithCustom") +public func _bjs_TextProcessor_processWithCustom(_ _self: UnsafeMutableRawPointer, _ textBytes: Int32, _ textLength: Int32, _ customTransform: Int32) -> Void { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).processWithCustom(_: String.bridgeJSLiftParameter(textBytes, textLength), customTransform: _BJS_Closure_20BridgeJSRuntimeTestsSiSSSd_SS.bridgeJSLift(customTransform)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_getTransform") +@_cdecl("bjs_TextProcessor_getTransform") +public func _bjs_TextProcessor_getTransform(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).getTransform() + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_processOptionalString") +@_cdecl("bjs_TextProcessor_processOptionalString") +public func _bjs_TextProcessor_processOptionalString(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Void { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).processOptionalString(_: _BJS_Closure_20BridgeJSRuntimeTestsSqSS_SS.bridgeJSLift(callback)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_processOptionalInt") +@_cdecl("bjs_TextProcessor_processOptionalInt") +public func _bjs_TextProcessor_processOptionalInt(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Void { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).processOptionalInt(_: _BJS_Closure_20BridgeJSRuntimeTestsSqSi_SS.bridgeJSLift(callback)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_processOptionalGreeter") +@_cdecl("bjs_TextProcessor_processOptionalGreeter") +public func _bjs_TextProcessor_processOptionalGreeter(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Void { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).processOptionalGreeter(_: _BJS_Closure_20BridgeJSRuntimeTestsSq7GreeterC_SS.bridgeJSLift(callback)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_makeOptionalStringFormatter") +@_cdecl("bjs_TextProcessor_makeOptionalStringFormatter") +public func _bjs_TextProcessor_makeOptionalStringFormatter(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).makeOptionalStringFormatter() + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_makeOptionalGreeterCreator") +@_cdecl("bjs_TextProcessor_makeOptionalGreeterCreator") +public func _bjs_TextProcessor_makeOptionalGreeterCreator(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).makeOptionalGreeterCreator() + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_processDirection") +@_cdecl("bjs_TextProcessor_processDirection") +public func _bjs_TextProcessor_processDirection(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Void { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).processDirection(_: _BJS_Closure_20BridgeJSRuntimeTests9DirectionO_SS.bridgeJSLift(callback)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_processTheme") +@_cdecl("bjs_TextProcessor_processTheme") +public func _bjs_TextProcessor_processTheme(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Void { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).processTheme(_: _BJS_Closure_20BridgeJSRuntimeTests5ThemeO_SS.bridgeJSLift(callback)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_processHttpStatus") +@_cdecl("bjs_TextProcessor_processHttpStatus") +public func _bjs_TextProcessor_processHttpStatus(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Int32 { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).processHttpStatus(_: _BJS_Closure_20BridgeJSRuntimeTests10HttpStatusO_Si.bridgeJSLift(callback)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_processAPIResult") +@_cdecl("bjs_TextProcessor_processAPIResult") +public func _bjs_TextProcessor_processAPIResult(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Void { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).processAPIResult(_: _BJS_Closure_20BridgeJSRuntimeTests9APIResultO_SS.bridgeJSLift(callback)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_makeDirectionChecker") +@_cdecl("bjs_TextProcessor_makeDirectionChecker") +public func _bjs_TextProcessor_makeDirectionChecker(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).makeDirectionChecker() + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_makeThemeValidator") +@_cdecl("bjs_TextProcessor_makeThemeValidator") +public func _bjs_TextProcessor_makeThemeValidator(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).makeThemeValidator() + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_makeStatusCodeExtractor") +@_cdecl("bjs_TextProcessor_makeStatusCodeExtractor") +public func _bjs_TextProcessor_makeStatusCodeExtractor(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).makeStatusCodeExtractor() + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_makeAPIResultHandler") +@_cdecl("bjs_TextProcessor_makeAPIResultHandler") +public func _bjs_TextProcessor_makeAPIResultHandler(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).makeAPIResultHandler() + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_processOptionalDirection") +@_cdecl("bjs_TextProcessor_processOptionalDirection") +public func _bjs_TextProcessor_processOptionalDirection(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Void { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).processOptionalDirection(_: _BJS_Closure_20BridgeJSRuntimeTestsSq9DirectionO_SS.bridgeJSLift(callback)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_processOptionalTheme") +@_cdecl("bjs_TextProcessor_processOptionalTheme") +public func _bjs_TextProcessor_processOptionalTheme(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Void { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).processOptionalTheme(_: _BJS_Closure_20BridgeJSRuntimeTestsSq5ThemeO_SS.bridgeJSLift(callback)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_processOptionalAPIResult") +@_cdecl("bjs_TextProcessor_processOptionalAPIResult") +public func _bjs_TextProcessor_processOptionalAPIResult(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Void { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).processOptionalAPIResult(_: _BJS_Closure_20BridgeJSRuntimeTestsSq9APIResultO_SS.bridgeJSLift(callback)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_makeOptionalDirectionFormatter") +@_cdecl("bjs_TextProcessor_makeOptionalDirectionFormatter") +public func _bjs_TextProcessor_makeOptionalDirectionFormatter(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).makeOptionalDirectionFormatter() + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_deinit") +@_cdecl("bjs_TextProcessor_deinit") +public func _bjs_TextProcessor_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension TextProcessor: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_TextProcessor_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_TextProcessor_wrap") +fileprivate func _bjs_TextProcessor_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_TextProcessor_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_OptionalHolder_init") +@_cdecl("bjs_OptionalHolder_init") +public func _bjs_OptionalHolder_init(_ nullableGreeterIsSome: Int32, _ nullableGreeterValue: UnsafeMutableRawPointer, _ undefinedNumberIsSome: Int32, _ undefinedNumberValue: Float64) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = OptionalHolder(nullableGreeter: Optional.bridgeJSLiftParameter(nullableGreeterIsSome, nullableGreeterValue), undefinedNumber: JSUndefinedOr.bridgeJSLiftParameter(undefinedNumberIsSome, undefinedNumberValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalHolder_nullableGreeter_get") +@_cdecl("bjs_OptionalHolder_nullableGreeter_get") +public func _bjs_OptionalHolder_nullableGreeter_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalHolder.bridgeJSLiftParameter(_self).nullableGreeter + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalHolder_nullableGreeter_set") +@_cdecl("bjs_OptionalHolder_nullableGreeter_set") +public func _bjs_OptionalHolder_nullableGreeter_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + OptionalHolder.bridgeJSLiftParameter(_self).nullableGreeter = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalHolder_undefinedNumber_get") +@_cdecl("bjs_OptionalHolder_undefinedNumber_get") +public func _bjs_OptionalHolder_undefinedNumber_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalHolder.bridgeJSLiftParameter(_self).undefinedNumber + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalHolder_undefinedNumber_set") +@_cdecl("bjs_OptionalHolder_undefinedNumber_set") +public func _bjs_OptionalHolder_undefinedNumber_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: Float64) -> Void { + #if arch(wasm32) + OptionalHolder.bridgeJSLiftParameter(_self).undefinedNumber = JSUndefinedOr.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalHolder_deinit") +@_cdecl("bjs_OptionalHolder_deinit") +public func _bjs_OptionalHolder_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension OptionalHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_OptionalHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalHolder_wrap") +fileprivate func _bjs_OptionalHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_OptionalHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_OptionalPropertyHolder_init") +@_cdecl("bjs_OptionalPropertyHolder_init") +public func _bjs_OptionalPropertyHolder_init(_ optionalNameIsSome: Int32, _ optionalNameBytes: Int32, _ optionalNameLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = OptionalPropertyHolder(optionalName: Optional.bridgeJSLiftParameter(optionalNameIsSome, optionalNameBytes, optionalNameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalName_get") +@_cdecl("bjs_OptionalPropertyHolder_optionalName_get") +public func _bjs_OptionalPropertyHolder_optionalName_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalName + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalName_set") +@_cdecl("bjs_OptionalPropertyHolder_optionalName_set") +public func _bjs_OptionalPropertyHolder_optionalName_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalName = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalAge_get") +@_cdecl("bjs_OptionalPropertyHolder_optionalAge_get") +public func _bjs_OptionalPropertyHolder_optionalAge_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalAge + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalAge_set") +@_cdecl("bjs_OptionalPropertyHolder_optionalAge_set") +public func _bjs_OptionalPropertyHolder_optionalAge_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalAge = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalGreeter_get") +@_cdecl("bjs_OptionalPropertyHolder_optionalGreeter_get") +public func _bjs_OptionalPropertyHolder_optionalGreeter_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalGreeter + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalGreeter_set") +@_cdecl("bjs_OptionalPropertyHolder_optionalGreeter_set") +public func _bjs_OptionalPropertyHolder_optionalGreeter_set(_ _self: UnsafeMutableRawPointer, _ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalGreeter = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_deinit") +@_cdecl("bjs_OptionalPropertyHolder_deinit") +public func _bjs_OptionalPropertyHolder_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension OptionalPropertyHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_OptionalPropertyHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalPropertyHolder_wrap") +fileprivate func _bjs_OptionalPropertyHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_OptionalPropertyHolder_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +@_expose(wasm, "bjs_Container_init") +@_cdecl("bjs_Container_init") +public func _bjs_Container_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let _tmp_config = Optional.bridgeJSLiftParameter() + let _tmp_location = DataPoint.bridgeJSLiftParameter() + let ret = Container(location: _tmp_location, config: _tmp_config) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_location_get") +@_cdecl("bjs_Container_location_get") +public func _bjs_Container_location_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Container.bridgeJSLiftParameter(_self).location + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_location_set") +@_cdecl("bjs_Container_location_set") +public func _bjs_Container_location_set(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Container.bridgeJSLiftParameter(_self).location = DataPoint.bridgeJSLiftParameter() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_config_get") +@_cdecl("bjs_Container_config_get") +public func _bjs_Container_config_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Container.bridgeJSLiftParameter(_self).config + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_config_set") +@_cdecl("bjs_Container_config_set") +public func _bjs_Container_config_set(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Container.bridgeJSLiftParameter(_self).config = Optional.bridgeJSLiftParameter() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_deinit") +@_cdecl("bjs_Container_deinit") +public func _bjs_Container_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Container: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Container_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Container_wrap") +fileprivate func _bjs_Container_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Container_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsApplyVoid_static") +fileprivate func bjs_ClosureSupportImports_jsApplyVoid_static(_ callback: Int32) -> Void +#else +fileprivate func bjs_ClosureSupportImports_jsApplyVoid_static(_ callback: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsApplyBool_static") +fileprivate func bjs_ClosureSupportImports_jsApplyBool_static(_ callback: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsApplyBool_static(_ callback: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsApplyInt_static") +fileprivate func bjs_ClosureSupportImports_jsApplyInt_static(_ value: Int32, _ transform: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsApplyInt_static(_ value: Int32, _ transform: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsApplyDouble_static") +fileprivate func bjs_ClosureSupportImports_jsApplyDouble_static(_ value: Float64, _ transform: Int32) -> Float64 +#else +fileprivate func bjs_ClosureSupportImports_jsApplyDouble_static(_ value: Float64, _ transform: Int32) -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsApplyString_static") +fileprivate func bjs_ClosureSupportImports_jsApplyString_static(_ value: Int32, _ transform: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsApplyString_static(_ value: Int32, _ transform: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsApplyJSObject_static") +fileprivate func bjs_ClosureSupportImports_jsApplyJSObject_static(_ value: Int32, _ transform: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsApplyJSObject_static(_ value: Int32, _ transform: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsMakeIntToInt_static") +fileprivate func bjs_ClosureSupportImports_jsMakeIntToInt_static(_ base: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsMakeIntToInt_static(_ base: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsMakeDoubleToDouble_static") +fileprivate func bjs_ClosureSupportImports_jsMakeDoubleToDouble_static(_ base: Float64) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsMakeDoubleToDouble_static(_ base: Float64) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsMakeStringToString_static") +fileprivate func bjs_ClosureSupportImports_jsMakeStringToString_static(_ prefix: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsMakeStringToString_static(_ prefix: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsCallTwice_static") +fileprivate func bjs_ClosureSupportImports_jsCallTwice_static(_ value: Int32, _ callback: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsCallTwice_static(_ value: Int32, _ callback: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsCallBinary_static") +fileprivate func bjs_ClosureSupportImports_jsCallBinary_static(_ callback: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsCallBinary_static(_ callback: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsCallTriple_static") +fileprivate func bjs_ClosureSupportImports_jsCallTriple_static(_ callback: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsCallTriple_static(_ callback: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsCallAfterRelease_static") +fileprivate func bjs_ClosureSupportImports_jsCallAfterRelease_static(_ callback: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsCallAfterRelease_static(_ callback: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsOptionalInvoke_static") +fileprivate func bjs_ClosureSupportImports_jsOptionalInvoke_static(_ callbackIsSome: Int32, _ callbackFuncRef: Int32) -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsOptionalInvoke_static(_ callbackIsSome: Int32, _ callbackFuncRef: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsStoreClosure_static") +fileprivate func bjs_ClosureSupportImports_jsStoreClosure_static(_ callback: Int32) -> Void +#else +fileprivate func bjs_ClosureSupportImports_jsStoreClosure_static(_ callback: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsCallStoredClosure_static") +fileprivate func bjs_ClosureSupportImports_jsCallStoredClosure_static() -> Void +#else +fileprivate func bjs_ClosureSupportImports_jsCallStoredClosure_static() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsHeapCount_static") +fileprivate func bjs_ClosureSupportImports_jsHeapCount_static() -> Int32 +#else +fileprivate func bjs_ClosureSupportImports_jsHeapCount_static() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_runJsClosureSupportTests_static") +fileprivate func bjs_ClosureSupportImports_runJsClosureSupportTests_static() -> Void +#else +fileprivate func bjs_ClosureSupportImports_runJsClosureSupportTests_static() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$ClosureSupportImports_jsApplyVoid(_ callback: JSTypedClosure<() -> Void>) throws(JSException) -> Void { + let callbackFuncRef = callback.bridgeJSLowerParameter() + bjs_ClosureSupportImports_jsApplyVoid_static(callbackFuncRef) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$ClosureSupportImports_jsApplyBool(_ callback: JSTypedClosure<() -> Bool>) throws(JSException) -> Bool { + let callbackFuncRef = callback.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsApplyBool_static(callbackFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return Bool.bridgeJSLiftReturn(ret) +} + +func _$ClosureSupportImports_jsApplyInt(_ value: Int, _ transform: JSTypedClosure<(Int) -> Int>) throws(JSException) -> Int { + let valueValue = value.bridgeJSLowerParameter() + let transformFuncRef = transform.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsApplyInt_static(valueValue, transformFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return Int.bridgeJSLiftReturn(ret) +} + +func _$ClosureSupportImports_jsApplyDouble(_ value: Double, _ transform: JSTypedClosure<(Double) -> Double>) throws(JSException) -> Double { + let valueValue = value.bridgeJSLowerParameter() + let transformFuncRef = transform.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsApplyDouble_static(valueValue, transformFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return Double.bridgeJSLiftReturn(ret) +} + +func _$ClosureSupportImports_jsApplyString(_ value: String, _ transform: JSTypedClosure<(String) -> String>) throws(JSException) -> String { + let valueValue = value.bridgeJSLowerParameter() + let transformFuncRef = transform.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsApplyString_static(valueValue, transformFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +func _$ClosureSupportImports_jsApplyJSObject(_ value: JSObject, _ transform: JSTypedClosure<(JSObject) -> JSObject>) throws(JSException) -> JSObject { + let valueValue = value.bridgeJSLowerParameter() + let transformFuncRef = transform.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsApplyJSObject_static(valueValue, transformFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + +func _$ClosureSupportImports_jsMakeIntToInt(_ base: Int) throws(JSException) -> (Int) -> Int { + let baseValue = base.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsMakeIntToInt_static(baseValue) + if let error = _swift_js_take_exception() { + throw error + } + return _BJS_Closure_20BridgeJSRuntimeTestsSi_Si.bridgeJSLift(ret) +} + +func _$ClosureSupportImports_jsMakeDoubleToDouble(_ base: Double) throws(JSException) -> (Double) -> Double { + let baseValue = base.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsMakeDoubleToDouble_static(baseValue) + if let error = _swift_js_take_exception() { + throw error + } + return _BJS_Closure_20BridgeJSRuntimeTestsSd_Sd.bridgeJSLift(ret) +} + +func _$ClosureSupportImports_jsMakeStringToString(_ prefix: String) throws(JSException) -> (String) -> String { + let prefixValue = prefix.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsMakeStringToString_static(prefixValue) + if let error = _swift_js_take_exception() { + throw error + } + return _BJS_Closure_20BridgeJSRuntimeTestsSS_SS.bridgeJSLift(ret) +} + +func _$ClosureSupportImports_jsCallTwice(_ value: Int, _ callback: JSTypedClosure<(Int) -> Void>) throws(JSException) -> Int { + let valueValue = value.bridgeJSLowerParameter() + let callbackFuncRef = callback.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsCallTwice_static(valueValue, callbackFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return Int.bridgeJSLiftReturn(ret) +} + +func _$ClosureSupportImports_jsCallBinary(_ callback: JSTypedClosure<(Int, Int) -> Int>) throws(JSException) -> Int { + let callbackFuncRef = callback.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsCallBinary_static(callbackFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return Int.bridgeJSLiftReturn(ret) +} + +func _$ClosureSupportImports_jsCallTriple(_ callback: JSTypedClosure<(Int, Int, Int) -> Int>) throws(JSException) -> Int { + let callbackFuncRef = callback.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsCallTriple_static(callbackFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return Int.bridgeJSLiftReturn(ret) +} + +func _$ClosureSupportImports_jsCallAfterRelease(_ callback: JSTypedClosure<() -> Void>) throws(JSException) -> String { + let callbackFuncRef = callback.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsCallAfterRelease_static(callbackFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +func _$ClosureSupportImports_jsOptionalInvoke(_ callback: Optional Bool>>) throws(JSException) -> Bool { + let (callbackIsSome, callbackFuncRef) = callback.bridgeJSLowerParameter() + let ret = bjs_ClosureSupportImports_jsOptionalInvoke_static(callbackIsSome, callbackFuncRef) + if let error = _swift_js_take_exception() { + throw error + } + return Bool.bridgeJSLiftReturn(ret) +} + +func _$ClosureSupportImports_jsStoreClosure(_ callback: JSTypedClosure<() -> Void>) throws(JSException) -> Void { + let callbackFuncRef = callback.bridgeJSLowerParameter() + bjs_ClosureSupportImports_jsStoreClosure_static(callbackFuncRef) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$ClosureSupportImports_jsCallStoredClosure() throws(JSException) -> Void { + bjs_ClosureSupportImports_jsCallStoredClosure_static() + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$ClosureSupportImports_jsHeapCount() throws(JSException) -> Int { + let ret = bjs_ClosureSupportImports_jsHeapCount_static() + if let error = _swift_js_take_exception() { + throw error + } + return Int.bridgeJSLiftReturn(ret) +} + +func _$ClosureSupportImports_runJsClosureSupportTests() throws(JSException) -> Void { + bjs_ClosureSupportImports_runJsClosureSupportTests_static() + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripDictionary") +fileprivate func bjs_jsRoundTripDictionary() -> Void +#else +fileprivate func bjs_jsRoundTripDictionary() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripDictionary(_ values: [String: Int]) throws(JSException) -> [String: Int] { + let _ = values.bridgeJSLowerParameter() + bjs_jsRoundTripDictionary() + if let error = _swift_js_take_exception() { + throw error + } + return [String: Int].bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripDictionaryBool") +fileprivate func bjs_jsRoundTripDictionaryBool() -> Void +#else +fileprivate func bjs_jsRoundTripDictionaryBool() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripDictionaryBool(_ values: [String: Bool]) throws(JSException) -> [String: Bool] { + let _ = values.bridgeJSLowerParameter() + bjs_jsRoundTripDictionaryBool() + if let error = _swift_js_take_exception() { + throw error + } + return [String: Bool].bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripDictionaryDouble") +fileprivate func bjs_jsRoundTripDictionaryDouble() -> Void +#else +fileprivate func bjs_jsRoundTripDictionaryDouble() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripDictionaryDouble(_ values: [String: Double]) throws(JSException) -> [String: Double] { + let _ = values.bridgeJSLowerParameter() + bjs_jsRoundTripDictionaryDouble() + if let error = _swift_js_take_exception() { + throw error + } + return [String: Double].bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripDictionaryJSObject") +fileprivate func bjs_jsRoundTripDictionaryJSObject() -> Void +#else +fileprivate func bjs_jsRoundTripDictionaryJSObject() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripDictionaryJSObject(_ values: [String: JSObject]) throws(JSException) -> [String: JSObject] { + let _ = values.bridgeJSLowerParameter() + bjs_jsRoundTripDictionaryJSObject() + if let error = _swift_js_take_exception() { + throw error + } + return [String: JSObject].bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripDictionaryJSValue") +fileprivate func bjs_jsRoundTripDictionaryJSValue() -> Void +#else +fileprivate func bjs_jsRoundTripDictionaryJSValue() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripDictionaryJSValue(_ values: [String: JSValue]) throws(JSException) -> [String: JSValue] { + let _ = values.bridgeJSLowerParameter() + bjs_jsRoundTripDictionaryJSValue() + if let error = _swift_js_take_exception() { + throw error + } + return [String: JSValue].bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripNestedDictionary") +fileprivate func bjs_jsRoundTripNestedDictionary() -> Void +#else +fileprivate func bjs_jsRoundTripNestedDictionary() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripNestedDictionary(_ values: [String: [Double]]) throws(JSException) -> [String: [Double]] { + let _ = values.bridgeJSLowerParameter() + bjs_jsRoundTripNestedDictionary() + if let error = _swift_js_take_exception() { + throw error + } + return [String: [Double]].bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripOptionalDictionary") +fileprivate func bjs_jsRoundTripOptionalDictionary(_ values: Int32) -> Void +#else +fileprivate func bjs_jsRoundTripOptionalDictionary(_ values: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripOptionalDictionary(_ values: Optional<[String: String]>) throws(JSException) -> Optional<[String: String]> { + let valuesIsSome = values.bridgeJSLowerParameter() + bjs_jsRoundTripOptionalDictionary(valuesIsSome) + if let error = _swift_js_take_exception() { + throw error + } + return Optional<[String: String]>.bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripUndefinedDictionary") +fileprivate func bjs_jsRoundTripUndefinedDictionary(_ values: Int32) -> Void +#else +fileprivate func bjs_jsRoundTripUndefinedDictionary(_ values: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripUndefinedDictionary(_ values: JSUndefinedOr<[String: Int]>) throws(JSException) -> JSUndefinedOr<[String: Int]> { + let valuesIsSome = values.bridgeJSLowerParameter() + bjs_jsRoundTripUndefinedDictionary(valuesIsSome) + if let error = _swift_js_take_exception() { + throw error + } + return JSUndefinedOr<[String: Int]>.bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Foo_init") +fileprivate func bjs_Foo_init(_ value: Int32) -> Int32 +#else +fileprivate func bjs_Foo_init(_ value: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Foo_value_get") +fileprivate func bjs_Foo_value_get(_ self: Int32) -> Int32 +#else +fileprivate func bjs_Foo_value_get(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$Foo_init(_ value: String) throws(JSException) -> JSObject { + let valueValue = value.bridgeJSLowerParameter() + let ret = bjs_Foo_init(valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + +func _$Foo_value_get(_ self: JSObject) throws(JSException) -> String { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_Foo_value_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_globalObject1_get") +fileprivate func bjs_globalObject1_get() -> Void +#else +fileprivate func bjs_globalObject1_get() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$globalObject1_get() throws(JSException) -> JSValue { + bjs_globalObject1_get() + if let error = _swift_js_take_exception() { + throw error + } + return JSValue.bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripVoid") +fileprivate func bjs_jsRoundTripVoid() -> Void +#else +fileprivate func bjs_jsRoundTripVoid() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripVoid() throws(JSException) -> Void { + bjs_jsRoundTripVoid() + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripNumber") +fileprivate func bjs_jsRoundTripNumber(_ v: Float64) -> Float64 +#else +fileprivate func bjs_jsRoundTripNumber(_ v: Float64) -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripNumber(_ v: Double) throws(JSException) -> Double { + let vValue = v.bridgeJSLowerParameter() + let ret = bjs_jsRoundTripNumber(vValue) + if let error = _swift_js_take_exception() { + throw error + } + return Double.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripBool") +fileprivate func bjs_jsRoundTripBool(_ v: Int32) -> Int32 +#else +fileprivate func bjs_jsRoundTripBool(_ v: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripBool(_ v: Bool) throws(JSException) -> Bool { + let vValue = v.bridgeJSLowerParameter() + let ret = bjs_jsRoundTripBool(vValue) + if let error = _swift_js_take_exception() { + throw error + } + return Bool.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripString") +fileprivate func bjs_jsRoundTripString(_ v: Int32) -> Int32 +#else +fileprivate func bjs_jsRoundTripString(_ v: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripString(_ v: String) throws(JSException) -> String { + let vValue = v.bridgeJSLowerParameter() + let ret = bjs_jsRoundTripString(vValue) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripJSValue") +fileprivate func bjs_jsRoundTripJSValue(_ vKind: Int32, _ vPayload1: Int32, _ vPayload2: Float64) -> Void +#else +fileprivate func bjs_jsRoundTripJSValue(_ vKind: Int32, _ vPayload1: Int32, _ vPayload2: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripJSValue(_ v: JSValue) throws(JSException) -> JSValue { + let (vKind, vPayload1, vPayload2) = v.bridgeJSLowerParameter() + bjs_jsRoundTripJSValue(vKind, vPayload1, vPayload2) + if let error = _swift_js_take_exception() { + throw error + } + return JSValue.bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripJSValueArray") +fileprivate func bjs_jsRoundTripJSValueArray() -> Void +#else +fileprivate func bjs_jsRoundTripJSValueArray() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripJSValueArray(_ v: [JSValue]) throws(JSException) -> [JSValue] { + let _ = v.bridgeJSLowerParameter() + bjs_jsRoundTripJSValueArray() + if let error = _swift_js_take_exception() { + throw error + } + return [JSValue].bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripOptionalJSValueArray") +fileprivate func bjs_jsRoundTripOptionalJSValueArray(_ v: Int32) -> Void +#else +fileprivate func bjs_jsRoundTripOptionalJSValueArray(_ v: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripOptionalJSValueArray(_ v: Optional<[JSValue]>) throws(JSException) -> Optional<[JSValue]> { + let vIsSome = v.bridgeJSLowerParameter() + bjs_jsRoundTripOptionalJSValueArray(vIsSome) + if let error = _swift_js_take_exception() { + throw error + } + return Optional<[JSValue]>.bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsThrowOrVoid") +fileprivate func bjs_jsThrowOrVoid(_ shouldThrow: Int32) -> Void +#else +fileprivate func bjs_jsThrowOrVoid(_ shouldThrow: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsThrowOrVoid(_ shouldThrow: Bool) throws(JSException) -> Void { + let shouldThrowValue = shouldThrow.bridgeJSLowerParameter() + bjs_jsThrowOrVoid(shouldThrowValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsThrowOrNumber") +fileprivate func bjs_jsThrowOrNumber(_ shouldThrow: Int32) -> Float64 +#else +fileprivate func bjs_jsThrowOrNumber(_ shouldThrow: Int32) -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsThrowOrNumber(_ shouldThrow: Bool) throws(JSException) -> Double { + let shouldThrowValue = shouldThrow.bridgeJSLowerParameter() + let ret = bjs_jsThrowOrNumber(shouldThrowValue) + if let error = _swift_js_take_exception() { + throw error + } + return Double.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsThrowOrBool") +fileprivate func bjs_jsThrowOrBool(_ shouldThrow: Int32) -> Int32 +#else +fileprivate func bjs_jsThrowOrBool(_ shouldThrow: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsThrowOrBool(_ shouldThrow: Bool) throws(JSException) -> Bool { + let shouldThrowValue = shouldThrow.bridgeJSLowerParameter() + let ret = bjs_jsThrowOrBool(shouldThrowValue) + if let error = _swift_js_take_exception() { + throw error + } + return Bool.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsThrowOrString") +fileprivate func bjs_jsThrowOrString(_ shouldThrow: Int32) -> Int32 +#else +fileprivate func bjs_jsThrowOrString(_ shouldThrow: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsThrowOrString(_ shouldThrow: Bool) throws(JSException) -> String { + let shouldThrowValue = shouldThrow.bridgeJSLowerParameter() + let ret = bjs_jsThrowOrString(shouldThrowValue) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripFeatureFlag") +fileprivate func bjs_jsRoundTripFeatureFlag(_ flag: Int32) -> Int32 +#else +fileprivate func bjs_jsRoundTripFeatureFlag(_ flag: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripFeatureFlag(_ flag: FeatureFlag) throws(JSException) -> FeatureFlag { + let flagValue = flag.bridgeJSLowerParameter() + let ret = bjs_jsRoundTripFeatureFlag(flagValue) + if let error = _swift_js_take_exception() { + throw error + } + return FeatureFlag.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_runAsyncWorks") +fileprivate func bjs_runAsyncWorks() -> Int32 +#else +fileprivate func bjs_runAsyncWorks() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$runAsyncWorks() throws(JSException) -> JSPromise { + let ret = bjs_runAsyncWorks() + if let error = _swift_js_take_exception() { + throw error + } + 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_jsRoundTripNumberArray") +fileprivate func bjs_jsRoundTripNumberArray() -> Void +#else +fileprivate func bjs_jsRoundTripNumberArray() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripNumberArray(_ values: [Double]) throws(JSException) -> [Double] { + let _ = values.bridgeJSLowerParameter() + bjs_jsRoundTripNumberArray() + if let error = _swift_js_take_exception() { + throw error + } + return [Double].bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripStringArray") +fileprivate func bjs_jsRoundTripStringArray() -> Void +#else +fileprivate func bjs_jsRoundTripStringArray() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripStringArray(_ values: [String]) throws(JSException) -> [String] { + let _ = values.bridgeJSLowerParameter() + bjs_jsRoundTripStringArray() + if let error = _swift_js_take_exception() { + throw error + } + return [String].bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripBoolArray") +fileprivate func bjs_jsRoundTripBoolArray() -> Void +#else +fileprivate func bjs_jsRoundTripBoolArray() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripBoolArray(_ values: [Bool]) throws(JSException) -> [Bool] { + let _ = values.bridgeJSLowerParameter() + bjs_jsRoundTripBoolArray() + if let error = _swift_js_take_exception() { + throw error + } + return [Bool].bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsSumNumberArray") +fileprivate func bjs_jsSumNumberArray() -> Float64 +#else +fileprivate func bjs_jsSumNumberArray() -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsSumNumberArray(_ values: [Double]) throws(JSException) -> Double { + let _ = values.bridgeJSLowerParameter() + let ret = bjs_jsSumNumberArray() + if let error = _swift_js_take_exception() { + throw error + } + return Double.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsCreateNumberArray") +fileprivate func bjs_jsCreateNumberArray() -> Void +#else +fileprivate func bjs_jsCreateNumberArray() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsCreateNumberArray() throws(JSException) -> [Double] { + bjs_jsCreateNumberArray() + if let error = _swift_js_take_exception() { + throw error + } + return [Double].bridgeJSLiftReturn() +} + +#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 +#else +fileprivate func bjs_JsGreeter_init(_ name: Int32, _ prefix: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JsGreeter_name_get") +fileprivate func bjs_JsGreeter_name_get(_ self: Int32) -> Int32 +#else +fileprivate func bjs_JsGreeter_name_get(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JsGreeter_prefix_get") +fileprivate func bjs_JsGreeter_prefix_get(_ self: Int32) -> Int32 +#else +fileprivate func bjs_JsGreeter_prefix_get(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JsGreeter_name_set") +fileprivate func bjs_JsGreeter_name_set(_ self: Int32, _ newValue: Int32) -> Void +#else +fileprivate func bjs_JsGreeter_name_set(_ self: Int32, _ newValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JsGreeter_greet") +fileprivate func bjs_JsGreeter_greet(_ self: Int32) -> Int32 +#else +fileprivate func bjs_JsGreeter_greet(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JsGreeter_changeName") +fileprivate func bjs_JsGreeter_changeName(_ self: Int32, _ name: Int32) -> Void +#else +fileprivate func bjs_JsGreeter_changeName(_ self: Int32, _ name: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$JsGreeter_init(_ name: String, _ prefix: String) throws(JSException) -> JSObject { + let nameValue = name.bridgeJSLowerParameter() + let prefixValue = prefix.bridgeJSLowerParameter() + let ret = bjs_JsGreeter_init(nameValue, prefixValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + +func _$JsGreeter_name_get(_ self: JSObject) throws(JSException) -> String { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_JsGreeter_name_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +func _$JsGreeter_prefix_get(_ self: JSObject) throws(JSException) -> String { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_JsGreeter_prefix_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +func _$JsGreeter_name_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let newValueValue = newValue.bridgeJSLowerParameter() + bjs_JsGreeter_name_set(selfValue, newValueValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$JsGreeter_greet(_ self: JSObject) throws(JSException) -> String { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_JsGreeter_greet(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +func _$JsGreeter_changeName(_ self: JSObject, _ name: String) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let nameValue = name.bridgeJSLowerParameter() + bjs_JsGreeter_changeName(selfValue, nameValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +#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_StaticBox_init") +fileprivate func bjs_StaticBox_init(_ value: Float64) -> Int32 +#else +fileprivate func bjs_StaticBox_init(_ value: Float64) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_StaticBox_create_static") +fileprivate func bjs_StaticBox_create_static(_ value: Float64) -> Int32 +#else +fileprivate func bjs_StaticBox_create_static(_ value: Float64) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_StaticBox_value_static") +fileprivate func bjs_StaticBox_value_static() -> Float64 +#else +fileprivate func bjs_StaticBox_value_static() -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_StaticBox_makeDefault_static") +fileprivate func bjs_StaticBox_makeDefault_static() -> Int32 +#else +fileprivate func bjs_StaticBox_makeDefault_static() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_StaticBox_with_dashes_static") +fileprivate func bjs_StaticBox_with_dashes_static() -> Int32 +#else +fileprivate func bjs_StaticBox_with_dashes_static() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_StaticBox_value") +fileprivate func bjs_StaticBox_value(_ self: Int32) -> Float64 +#else +fileprivate func bjs_StaticBox_value(_ self: Int32) -> Float64 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$StaticBox_init(_ value: Double) throws(JSException) -> JSObject { + let valueValue = value.bridgeJSLowerParameter() + let ret = bjs_StaticBox_init(valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + +func _$StaticBox_create(_ value: Double) throws(JSException) -> StaticBox { + let valueValue = value.bridgeJSLowerParameter() + let ret = bjs_StaticBox_create_static(valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return StaticBox.bridgeJSLiftReturn(ret) +} + +func _$StaticBox_value() throws(JSException) -> Double { + let ret = bjs_StaticBox_value_static() + if let error = _swift_js_take_exception() { + throw error + } + return Double.bridgeJSLiftReturn(ret) +} + +func _$StaticBox_makeDefault() throws(JSException) -> StaticBox { + let ret = bjs_StaticBox_makeDefault_static() + if let error = _swift_js_take_exception() { + throw error + } + return StaticBox.bridgeJSLiftReturn(ret) +} + +func _$StaticBox_with_dashes() throws(JSException) -> StaticBox { + let ret = bjs_StaticBox_with_dashes_static() + if let error = _swift_js_take_exception() { + throw error + } + return StaticBox.bridgeJSLiftReturn(ret) +} + +func _$StaticBox_value(_ self: JSObject) throws(JSException) -> Double { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_StaticBox_value(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return Double.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_jsRoundTripIntArray") +fileprivate func bjs_jsRoundTripIntArray() -> Void +#else +fileprivate func bjs_jsRoundTripIntArray() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsRoundTripIntArray(_ items: [Int]) throws(JSException) -> [Int] { + let _ = items.bridgeJSLowerParameter() + bjs_jsRoundTripIntArray() + if let error = _swift_js_take_exception() { + throw error + } + return [Int].bridgeJSLiftReturn() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsArrayLength") +fileprivate func bjs_jsArrayLength() -> Int32 +#else +fileprivate func bjs_jsArrayLength() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsArrayLength(_ items: [Int]) throws(JSException) -> Int { + let _ = items.bridgeJSLowerParameter() + let ret = bjs_jsArrayLength() + if let error = _swift_js_take_exception() { + throw error + } + return Int.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_makeArrayHost") +fileprivate func bjs_makeArrayHost() -> Int32 +#else +fileprivate func bjs_makeArrayHost() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$makeArrayHost(_ numbers: [Int], _ labels: [String]) throws(JSException) -> ArrayHost { + let _ = labels.bridgeJSLowerParameter() + let _ = numbers.bridgeJSLowerParameter() + let ret = bjs_makeArrayHost() + if let error = _swift_js_take_exception() { + throw error + } + return ArrayHost.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ArrayHost_init") +fileprivate func bjs_ArrayHost_init() -> Int32 +#else +fileprivate func bjs_ArrayHost_init() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ArrayHost_numbers_get") +fileprivate func bjs_ArrayHost_numbers_get(_ self: Int32) -> Void +#else +fileprivate func bjs_ArrayHost_numbers_get(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ArrayHost_labels_get") +fileprivate func bjs_ArrayHost_labels_get(_ self: Int32) -> Void +#else +fileprivate func bjs_ArrayHost_labels_get(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ArrayHost_numbers_set") +fileprivate func bjs_ArrayHost_numbers_set(_ self: Int32) -> Void +#else +fileprivate func bjs_ArrayHost_numbers_set(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ArrayHost_labels_set") +fileprivate func bjs_ArrayHost_labels_set(_ self: Int32) -> Void +#else +fileprivate func bjs_ArrayHost_labels_set(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ArrayHost_concatNumbers") +fileprivate func bjs_ArrayHost_concatNumbers(_ self: Int32) -> Void +#else +fileprivate func bjs_ArrayHost_concatNumbers(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ArrayHost_concatLabels") +fileprivate func bjs_ArrayHost_concatLabels(_ self: Int32) -> Void +#else +fileprivate func bjs_ArrayHost_concatLabels(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ArrayHost_firstLabel") +fileprivate func bjs_ArrayHost_firstLabel(_ self: Int32) -> Int32 +#else +fileprivate func bjs_ArrayHost_firstLabel(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$ArrayHost_init(_ numbers: [Int], _ labels: [String]) throws(JSException) -> JSObject { + let _ = labels.bridgeJSLowerParameter() + let _ = numbers.bridgeJSLowerParameter() + let ret = bjs_ArrayHost_init() + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + +func _$ArrayHost_numbers_get(_ self: JSObject) throws(JSException) -> [Int] { + let selfValue = self.bridgeJSLowerParameter() + bjs_ArrayHost_numbers_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return [Int].bridgeJSLiftReturn() +} + +func _$ArrayHost_labels_get(_ self: JSObject) throws(JSException) -> [String] { + let selfValue = self.bridgeJSLowerParameter() + bjs_ArrayHost_labels_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return [String].bridgeJSLiftReturn() +} + +func _$ArrayHost_numbers_set(_ self: JSObject, _ newValue: [Int]) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let _ = newValue.bridgeJSLowerParameter() + bjs_ArrayHost_numbers_set(selfValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$ArrayHost_labels_set(_ self: JSObject, _ newValue: [String]) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let _ = newValue.bridgeJSLowerParameter() + bjs_ArrayHost_labels_set(selfValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$ArrayHost_concatNumbers(_ self: JSObject, _ values: [Int]) throws(JSException) -> [Int] { + let selfValue = self.bridgeJSLowerParameter() + let _ = values.bridgeJSLowerParameter() + bjs_ArrayHost_concatNumbers(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return [Int].bridgeJSLiftReturn() +} + +func _$ArrayHost_concatLabels(_ self: JSObject, _ values: [String]) throws(JSException) -> [String] { + let selfValue = self.bridgeJSLowerParameter() + let _ = values.bridgeJSLowerParameter() + bjs_ArrayHost_concatLabels(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return [String].bridgeJSLiftReturn() +} + +func _$ArrayHost_firstLabel(_ self: JSObject, _ values: [String]) throws(JSException) -> String { + let selfValue = self.bridgeJSLowerParameter() + let _ = values.bridgeJSLowerParameter() + let ret = bjs_ArrayHost_firstLabel(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return String.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) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_MyJSClassInternal_init") +fileprivate func bjs_MyJSClassInternal_init() -> Int32 +#else +fileprivate func bjs_MyJSClassInternal_init() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$MyJSClassInternal_init() throws(JSException) -> JSObject { + let ret = bjs_MyJSClassInternal_init() + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_MyJSClassPublic_init") +fileprivate func bjs_MyJSClassPublic_init() -> Int32 +#else +fileprivate func bjs_MyJSClassPublic_init() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$MyJSClassPublic_init() throws(JSException) -> JSObject { + let ret = bjs_MyJSClassPublic_init() + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_MyJSClassPackage_init") +fileprivate func bjs_MyJSClassPackage_init() -> Int32 +#else +fileprivate func bjs_MyJSClassPackage_init() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif + +func _$MyJSClassPackage_init() throws(JSException) -> JSObject { + let ret = bjs_MyJSClassPackage_init() + if let error = _swift_js_take_exception() { + throw error + } + return JSObject.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsFunctionWithPackageAccess") +fileprivate func bjs_jsFunctionWithPackageAccess() -> Void +#else +fileprivate func bjs_jsFunctionWithPackageAccess() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsFunctionWithPackageAccess() throws(JSException) -> Void { + bjs_jsFunctionWithPackageAccess() + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsFunctionWithPublicAccess") +fileprivate func bjs_jsFunctionWithPublicAccess() -> Void +#else +fileprivate func bjs_jsFunctionWithPublicAccess() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsFunctionWithPublicAccess() throws(JSException) -> Void { + bjs_jsFunctionWithPublicAccess() + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsFunctionWithInternalAccess") +fileprivate func bjs_jsFunctionWithInternalAccess() -> Void +#else +fileprivate func bjs_jsFunctionWithInternalAccess() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsFunctionWithInternalAccess() throws(JSException) -> Void { + bjs_jsFunctionWithInternalAccess() + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsFunctionWithFilePrivateAccess") +fileprivate func bjs_jsFunctionWithFilePrivateAccess() -> Void +#else +fileprivate func bjs_jsFunctionWithFilePrivateAccess() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsFunctionWithFilePrivateAccess() throws(JSException) -> Void { + bjs_jsFunctionWithFilePrivateAccess() + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsFunctionWithPrivateAccess") +fileprivate func bjs_jsFunctionWithPrivateAccess() -> Void +#else +fileprivate func bjs_jsFunctionWithPrivateAccess() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$jsFunctionWithPrivateAccess() throws(JSException) -> Void { + bjs_jsFunctionWithPrivateAccess() + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalSupportImports_jsRoundTripOptionalNumberNull_static") +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalNumberNull_static(_ valueIsSome: Int32, _ valueValue: Int32) -> Void +#else +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalNumberNull_static(_ valueIsSome: Int32, _ valueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalSupportImports_jsRoundTripOptionalNumberUndefined_static") +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalNumberUndefined_static(_ valueIsSome: Int32, _ valueValue: Int32) -> Void +#else +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalNumberUndefined_static(_ valueIsSome: Int32, _ valueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalSupportImports_jsRoundTripOptionalStringNull_static") +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringNull_static(_ nameIsSome: Int32, _ nameValue: Int32) -> Void +#else +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringNull_static(_ nameIsSome: Int32, _ nameValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalSupportImports_jsRoundTripOptionalStringUndefined_static") +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringUndefined_static(_ nameIsSome: Int32, _ nameValue: Int32) -> Void +#else +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringUndefined_static(_ nameIsSome: Int32, _ nameValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalSupportImports_runJsOptionalSupportTests_static") +fileprivate func bjs_OptionalSupportImports_runJsOptionalSupportTests_static() -> Void +#else +fileprivate func bjs_OptionalSupportImports_runJsOptionalSupportTests_static() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$OptionalSupportImports_jsRoundTripOptionalNumberNull(_ value: Optional) throws(JSException) -> Optional { + let (valueIsSome, valueValue) = value.bridgeJSLowerParameter() + bjs_OptionalSupportImports_jsRoundTripOptionalNumberNull_static(valueIsSome, valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturnFromSideChannel() +} + +func _$OptionalSupportImports_jsRoundTripOptionalNumberUndefined(_ value: JSUndefinedOr) throws(JSException) -> JSUndefinedOr { + let (valueIsSome, valueValue) = value.bridgeJSLowerParameter() + bjs_OptionalSupportImports_jsRoundTripOptionalNumberUndefined_static(valueIsSome, valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSUndefinedOr.bridgeJSLiftReturnFromSideChannel() +} + +func _$OptionalSupportImports_jsRoundTripOptionalStringNull(_ name: Optional) throws(JSException) -> Optional { + let (nameIsSome, nameValue) = name.bridgeJSLowerParameter() + bjs_OptionalSupportImports_jsRoundTripOptionalStringNull_static(nameIsSome, nameValue) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturnFromSideChannel() +} + +func _$OptionalSupportImports_jsRoundTripOptionalStringUndefined(_ name: JSUndefinedOr) throws(JSException) -> JSUndefinedOr { + let (nameIsSome, nameValue) = name.bridgeJSLowerParameter() + bjs_OptionalSupportImports_jsRoundTripOptionalStringUndefined_static(nameIsSome, nameValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSUndefinedOr.bridgeJSLiftReturnFromSideChannel() +} + +func _$OptionalSupportImports_runJsOptionalSupportTests() throws(JSException) -> Void { + bjs_OptionalSupportImports_runJsOptionalSupportTests_static() + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_gc") +fileprivate func bjs_gc() -> Void +#else +fileprivate func bjs_gc() -> Void { + fatalError("Only available on WebAssembly") +} +#endif + +func _$gc() throws(JSException) -> Void { + bjs_gc() + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_SwiftClassSupportImports_jsRoundTripGreeter_static") +fileprivate func bjs_SwiftClassSupportImports_jsRoundTripGreeter_static(_ greeter: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer +#else +fileprivate func bjs_SwiftClassSupportImports_jsRoundTripGreeter_static(_ greeter: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + fatalError("Only available on WebAssembly") +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_SwiftClassSupportImports_jsRoundTripOptionalGreeter_static") +fileprivate func bjs_SwiftClassSupportImports_jsRoundTripOptionalGreeter_static(_ greeterIsSome: Int32, _ greeterPointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer +#else +fileprivate func bjs_SwiftClassSupportImports_jsRoundTripOptionalGreeter_static(_ greeterIsSome: Int32, _ greeterPointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + fatalError("Only available on WebAssembly") +} +#endif + +func _$SwiftClassSupportImports_jsRoundTripGreeter(_ greeter: Greeter) throws(JSException) -> Greeter { + let greeterPointer = greeter.bridgeJSLowerParameter() + let ret = bjs_SwiftClassSupportImports_jsRoundTripGreeter_static(greeterPointer) + if let error = _swift_js_take_exception() { + throw error + } + return Greeter.bridgeJSLiftReturn(ret) +} + +func _$SwiftClassSupportImports_jsRoundTripOptionalGreeter(_ greeter: Optional) throws(JSException) -> Optional { + let (greeterIsSome, greeterPointer) = greeter.bridgeJSLowerParameter() + let ret = bjs_SwiftClassSupportImports_jsRoundTripOptionalGreeter_static(greeterIsSome, greeterPointer) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturn(ret) +} \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ExportSwift.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ExportSwift.json deleted file mode 100644 index 97b86cecb..000000000 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ExportSwift.json +++ /dev/null @@ -1,783 +0,0 @@ -{ - "classes" : [ - { - "constructor" : { - "abiName" : "bjs_Greeter_init", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "parameters" : [ - { - "label" : "name", - "name" : "name", - "type" : { - "string" : { - - } - } - } - ] - }, - "methods" : [ - { - "abiName" : "bjs_Greeter_greet", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "greet", - "parameters" : [ - - ], - "returnType" : { - "string" : { - - } - } - }, - { - "abiName" : "bjs_Greeter_changeName", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "changeName", - "parameters" : [ - { - "label" : "name", - "name" : "name", - "type" : { - "string" : { - - } - } - } - ], - "returnType" : { - "void" : { - - } - } - } - ], - "name" : "Greeter" - }, - { - "methods" : [ - { - "abiName" : "bjs_Calculator_square", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "square", - "parameters" : [ - { - "label" : "value", - "name" : "value", - "type" : { - "int" : { - - } - } - } - ], - "returnType" : { - "int" : { - - } - } - }, - { - "abiName" : "bjs_Calculator_add", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "add", - "parameters" : [ - { - "label" : "a", - "name" : "a", - "type" : { - "int" : { - - } - } - }, - { - "label" : "b", - "name" : "b", - "type" : { - "int" : { - - } - } - } - ], - "returnType" : { - "int" : { - - } - } - } - ], - "name" : "Calculator" - } - ], - "functions" : [ - { - "abiName" : "bjs_roundTripVoid", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "roundTripVoid", - "parameters" : [ - - ], - "returnType" : { - "void" : { - - } - } - }, - { - "abiName" : "bjs_roundTripInt", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "roundTripInt", - "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "int" : { - - } - } - } - ], - "returnType" : { - "int" : { - - } - } - }, - { - "abiName" : "bjs_roundTripFloat", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "roundTripFloat", - "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "float" : { - - } - } - } - ], - "returnType" : { - "float" : { - - } - } - }, - { - "abiName" : "bjs_roundTripDouble", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "roundTripDouble", - "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "double" : { - - } - } - } - ], - "returnType" : { - "double" : { - - } - } - }, - { - "abiName" : "bjs_roundTripBool", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "roundTripBool", - "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "bool" : { - - } - } - } - ], - "returnType" : { - "bool" : { - - } - } - }, - { - "abiName" : "bjs_roundTripString", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "roundTripString", - "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "string" : { - - } - } - } - ], - "returnType" : { - "string" : { - - } - } - }, - { - "abiName" : "bjs_roundTripSwiftHeapObject", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "roundTripSwiftHeapObject", - "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } - } - } - ], - "returnType" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } - } - }, - { - "abiName" : "bjs_roundTripJSObject", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "roundTripJSObject", - "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "jsObject" : { - - } - } - } - ], - "returnType" : { - "jsObject" : { - - } - } - }, - { - "abiName" : "bjs_throwsSwiftError", - "effects" : { - "isAsync" : false, - "isThrows" : true - }, - "name" : "throwsSwiftError", - "parameters" : [ - { - "label" : "shouldThrow", - "name" : "shouldThrow", - "type" : { - "bool" : { - - } - } - } - ], - "returnType" : { - "void" : { - - } - } - }, - { - "abiName" : "bjs_throwsWithIntResult", - "effects" : { - "isAsync" : false, - "isThrows" : true - }, - "name" : "throwsWithIntResult", - "parameters" : [ - - ], - "returnType" : { - "int" : { - - } - } - }, - { - "abiName" : "bjs_throwsWithStringResult", - "effects" : { - "isAsync" : false, - "isThrows" : true - }, - "name" : "throwsWithStringResult", - "parameters" : [ - - ], - "returnType" : { - "string" : { - - } - } - }, - { - "abiName" : "bjs_throwsWithBoolResult", - "effects" : { - "isAsync" : false, - "isThrows" : true - }, - "name" : "throwsWithBoolResult", - "parameters" : [ - - ], - "returnType" : { - "bool" : { - - } - } - }, - { - "abiName" : "bjs_throwsWithFloatResult", - "effects" : { - "isAsync" : false, - "isThrows" : true - }, - "name" : "throwsWithFloatResult", - "parameters" : [ - - ], - "returnType" : { - "float" : { - - } - } - }, - { - "abiName" : "bjs_throwsWithDoubleResult", - "effects" : { - "isAsync" : false, - "isThrows" : true - }, - "name" : "throwsWithDoubleResult", - "parameters" : [ - - ], - "returnType" : { - "double" : { - - } - } - }, - { - "abiName" : "bjs_throwsWithSwiftHeapObjectResult", - "effects" : { - "isAsync" : false, - "isThrows" : true - }, - "name" : "throwsWithSwiftHeapObjectResult", - "parameters" : [ - - ], - "returnType" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } - } - }, - { - "abiName" : "bjs_throwsWithJSObjectResult", - "effects" : { - "isAsync" : false, - "isThrows" : true - }, - "name" : "throwsWithJSObjectResult", - "parameters" : [ - - ], - "returnType" : { - "jsObject" : { - - } - } - }, - { - "abiName" : "bjs_asyncRoundTripVoid", - "effects" : { - "isAsync" : true, - "isThrows" : false - }, - "name" : "asyncRoundTripVoid", - "parameters" : [ - - ], - "returnType" : { - "void" : { - - } - } - }, - { - "abiName" : "bjs_asyncRoundTripInt", - "effects" : { - "isAsync" : true, - "isThrows" : false - }, - "name" : "asyncRoundTripInt", - "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "int" : { - - } - } - } - ], - "returnType" : { - "int" : { - - } - } - }, - { - "abiName" : "bjs_asyncRoundTripFloat", - "effects" : { - "isAsync" : true, - "isThrows" : false - }, - "name" : "asyncRoundTripFloat", - "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "float" : { - - } - } - } - ], - "returnType" : { - "float" : { - - } - } - }, - { - "abiName" : "bjs_asyncRoundTripDouble", - "effects" : { - "isAsync" : true, - "isThrows" : false - }, - "name" : "asyncRoundTripDouble", - "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "double" : { - - } - } - } - ], - "returnType" : { - "double" : { - - } - } - }, - { - "abiName" : "bjs_asyncRoundTripBool", - "effects" : { - "isAsync" : true, - "isThrows" : false - }, - "name" : "asyncRoundTripBool", - "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "bool" : { - - } - } - } - ], - "returnType" : { - "bool" : { - - } - } - }, - { - "abiName" : "bjs_asyncRoundTripString", - "effects" : { - "isAsync" : true, - "isThrows" : false - }, - "name" : "asyncRoundTripString", - "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "string" : { - - } - } - } - ], - "returnType" : { - "string" : { - - } - } - }, - { - "abiName" : "bjs_asyncRoundTripSwiftHeapObject", - "effects" : { - "isAsync" : true, - "isThrows" : false - }, - "name" : "asyncRoundTripSwiftHeapObject", - "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } - } - } - ], - "returnType" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } - } - }, - { - "abiName" : "bjs_asyncRoundTripJSObject", - "effects" : { - "isAsync" : true, - "isThrows" : false - }, - "name" : "asyncRoundTripJSObject", - "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "jsObject" : { - - } - } - } - ], - "returnType" : { - "jsObject" : { - - } - } - }, - { - "abiName" : "bjs_takeGreeter", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "takeGreeter", - "parameters" : [ - { - "label" : "g", - "name" : "g", - "type" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } - } - }, - { - "label" : "name", - "name" : "name", - "type" : { - "string" : { - - } - } - } - ], - "returnType" : { - "void" : { - - } - } - }, - { - "abiName" : "bjs_createCalculator", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "createCalculator", - "parameters" : [ - - ], - "returnType" : { - "swiftHeapObject" : { - "_0" : "Calculator" - } - } - }, - { - "abiName" : "bjs_useCalculator", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "useCalculator", - "parameters" : [ - { - "label" : "calc", - "name" : "calc", - "type" : { - "swiftHeapObject" : { - "_0" : "Calculator" - } - } - }, - { - "label" : "x", - "name" : "x", - "type" : { - "int" : { - - } - } - }, - { - "label" : "y", - "name" : "y", - "type" : { - "int" : { - - } - } - } - ], - "returnType" : { - "int" : { - - } - } - }, - { - "abiName" : "bjs_testGreeterToJSValue", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "testGreeterToJSValue", - "parameters" : [ - - ], - "returnType" : { - "jsObject" : { - - } - } - }, - { - "abiName" : "bjs_testCalculatorToJSValue", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "testCalculatorToJSValue", - "parameters" : [ - - ], - "returnType" : { - "jsObject" : { - - } - } - }, - { - "abiName" : "bjs_testSwiftClassAsJSValue", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "testSwiftClassAsJSValue", - "parameters" : [ - { - "label" : "greeter", - "name" : "greeter", - "type" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } - } - } - ], - "returnType" : { - "jsObject" : { - - } - } - } - ], - "moduleName" : "BridgeJSRuntimeTests" -} \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ImportTS.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ImportTS.json deleted file mode 100644 index 82515fecb..000000000 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ImportTS.json +++ /dev/null @@ -1,233 +0,0 @@ -{ - "children" : [ - { - "functions" : [ - { - "name" : "jsRoundTripVoid", - "parameters" : [ - - ], - "returnType" : { - "void" : { - - } - } - }, - { - "name" : "jsRoundTripNumber", - "parameters" : [ - { - "name" : "v", - "type" : { - "double" : { - - } - } - } - ], - "returnType" : { - "double" : { - - } - } - }, - { - "name" : "jsRoundTripBool", - "parameters" : [ - { - "name" : "v", - "type" : { - "bool" : { - - } - } - } - ], - "returnType" : { - "bool" : { - - } - } - }, - { - "name" : "jsRoundTripString", - "parameters" : [ - { - "name" : "v", - "type" : { - "string" : { - - } - } - } - ], - "returnType" : { - "string" : { - - } - } - }, - { - "name" : "jsThrowOrVoid", - "parameters" : [ - { - "name" : "shouldThrow", - "type" : { - "bool" : { - - } - } - } - ], - "returnType" : { - "void" : { - - } - } - }, - { - "name" : "jsThrowOrNumber", - "parameters" : [ - { - "name" : "shouldThrow", - "type" : { - "bool" : { - - } - } - } - ], - "returnType" : { - "double" : { - - } - } - }, - { - "name" : "jsThrowOrBool", - "parameters" : [ - { - "name" : "shouldThrow", - "type" : { - "bool" : { - - } - } - } - ], - "returnType" : { - "bool" : { - - } - } - }, - { - "name" : "jsThrowOrString", - "parameters" : [ - { - "name" : "shouldThrow", - "type" : { - "bool" : { - - } - } - } - ], - "returnType" : { - "string" : { - - } - } - }, - { - "name" : "runAsyncWorks", - "parameters" : [ - - ], - "returnType" : { - "jsObject" : { - "_0" : "JSPromise" - } - } - } - ], - "types" : [ - { - "constructor" : { - "parameters" : [ - { - "name" : "name", - "type" : { - "string" : { - - } - } - }, - { - "name" : "prefix", - "type" : { - "string" : { - - } - } - } - ] - }, - "methods" : [ - { - "name" : "greet", - "parameters" : [ - - ], - "returnType" : { - "string" : { - - } - } - }, - { - "name" : "changeName", - "parameters" : [ - { - "name" : "name", - "type" : { - "string" : { - - } - } - } - ], - "returnType" : { - "void" : { - - } - } - } - ], - "name" : "JsGreeter", - "properties" : [ - { - "isReadonly" : false, - "name" : "name", - "type" : { - "string" : { - - } - } - }, - { - "isReadonly" : true, - "name" : "prefix", - "type" : { - "string" : { - - } - } - } - ] - } - ] - } - ], - "moduleName" : "BridgeJSRuntimeTests" -} \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json new file mode 100644 index 000000000..45acc8a9c --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json @@ -0,0 +1,15654 @@ +{ + "exported" : { + "classes" : [ + { + "methods" : [ + { + "abiName" : "bjs_ClosureSupportExports_static_makeIntToInt", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "makeIntToInt", + "parameters" : [ + { + "label" : "_", + "name" : "base", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSi_Si", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "int" : { + + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + "useJSTypedClosure" : false + } + }, + "staticContext" : { + "className" : { + "_0" : "ClosureSupportExports" + } + } + }, + { + "abiName" : "bjs_ClosureSupportExports_static_makeDoubleToDouble", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "makeDoubleToDouble", + "parameters" : [ + { + "label" : "_", + "name" : "base", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSd_Sd", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "double" : { + + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + "useJSTypedClosure" : false + } + }, + "staticContext" : { + "className" : { + "_0" : "ClosureSupportExports" + } + } + }, + { + "abiName" : "bjs_ClosureSupportExports_static_makeStringToString", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "makeStringToString", + "parameters" : [ + { + "label" : "_", + "name" : "prefix", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSS_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + }, + "staticContext" : { + "className" : { + "_0" : "ClosureSupportExports" + } + } + }, + { + "abiName" : "bjs_ClosureSupportExports_static_makeJSIntToInt", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "makeJSIntToInt", + "parameters" : [ + { + "label" : "_", + "name" : "base", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSi_Si", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "int" : { + + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + "useJSTypedClosure" : true + } + }, + "staticContext" : { + "className" : { + "_0" : "ClosureSupportExports" + } + } + }, + { + "abiName" : "bjs_ClosureSupportExports_static_makeJSDoubleToDouble", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "makeJSDoubleToDouble", + "parameters" : [ + { + "label" : "_", + "name" : "base", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSd_Sd", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "double" : { + + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + "useJSTypedClosure" : true + } + }, + "staticContext" : { + "className" : { + "_0" : "ClosureSupportExports" + } + } + }, + { + "abiName" : "bjs_ClosureSupportExports_static_makeJSStringToString", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "makeJSStringToString", + "parameters" : [ + { + "label" : "_", + "name" : "prefix", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSS_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : true + } + }, + "staticContext" : { + "className" : { + "_0" : "ClosureSupportExports" + } + } + } + ], + "name" : "ClosureSupportExports", + "properties" : [ + + ], + "swiftCallName" : "ClosureSupportExports" + }, + { + "constructor" : { + "abiName" : "bjs_Greeter_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ] + }, + "explicitAccessControl" : "public", + "methods" : [ + { + "abiName" : "bjs_Greeter_greet", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "greet", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_Greeter_changeName", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "changeName", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_Greeter_greetWith", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "greetWith", + "parameters" : [ + { + "label" : "greeter", + "name" : "greeter", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "label" : "customGreeting", + "name" : "customGreeting", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTests7GreeterC_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_Greeter_makeFormatter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeFormatter", + "parameters" : [ + { + "label" : "suffix", + "name" : "suffix", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSS_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_Greeter_static_makeCreator", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "makeCreator", + "parameters" : [ + { + "label" : "defaultName", + "name" : "defaultName", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSS_7GreeterC", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + "useJSTypedClosure" : false + } + }, + "staticContext" : { + "className" : { + "_0" : "Greeter" + } + } + }, + { + "abiName" : "bjs_Greeter_makeCustomGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeCustomGreeter", + "parameters" : [ + + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTests7GreeterC_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "name" : "Greeter", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "prefix", + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "Greeter" + }, + { + "methods" : [ + { + "abiName" : "bjs_Calculator_square", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "square", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_Calculator_add", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "add", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "int" : { + + } + } + }, + { + "label" : "b", + "name" : "b", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + } + } + ], + "name" : "Calculator", + "properties" : [ + + ], + "swiftCallName" : "Calculator" + }, + { + "explicitAccessControl" : "internal", + "methods" : [ + + ], + "name" : "InternalGreeter", + "properties" : [ + + ], + "swiftCallName" : "InternalGreeter" + }, + { + "explicitAccessControl" : "public", + "methods" : [ + + ], + "name" : "PublicGreeter", + "properties" : [ + + ], + "swiftCallName" : "PublicGreeter" + }, + { + "explicitAccessControl" : "package", + "methods" : [ + + ], + "name" : "PackageGreeter", + "properties" : [ + + ], + "swiftCallName" : "PackageGreeter" + }, + { + "constructor" : { + "abiName" : "bjs_Converter_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_Converter_toString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "toString", + "namespace" : [ + "Utils" + ], + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "Converter", + "namespace" : [ + "Utils" + ], + "properties" : [ + + ], + "swiftCallName" : "Utils.Converter" + }, + { + "constructor" : { + "abiName" : "bjs_HTTPServer_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_HTTPServer_call", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "call", + "namespace" : [ + "Networking", + "API" + ], + "parameters" : [ + { + "label" : "_", + "name" : "method", + "type" : { + "caseEnum" : { + "_0" : "Networking.API.Method" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "HTTPServer", + "namespace" : [ + "Networking", + "API" + ], + "properties" : [ + + ], + "swiftCallName" : "Networking.API.HTTPServer" + }, + { + "constructor" : { + "abiName" : "bjs_TestServer_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_TestServer_call", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "call", + "namespace" : [ + "Networking", + "APIV2", + "Internal" + ], + "parameters" : [ + { + "label" : "_", + "name" : "method", + "type" : { + "caseEnum" : { + "_0" : "Internal.SupportedMethod" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "TestServer", + "namespace" : [ + "Networking", + "APIV2", + "Internal" + ], + "properties" : [ + + ], + "swiftCallName" : "Internal.TestServer" + }, + { + "constructor" : { + "abiName" : "bjs_SimplePropertyHolder_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "SimplePropertyHolder", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "swiftCallName" : "SimplePropertyHolder" + }, + { + "constructor" : { + "abiName" : "bjs_PropertyHolder_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "intValue", + "name" : "intValue", + "type" : { + "int" : { + + } + } + }, + { + "label" : "floatValue", + "name" : "floatValue", + "type" : { + "float" : { + + } + } + }, + { + "label" : "doubleValue", + "name" : "doubleValue", + "type" : { + "double" : { + + } + } + }, + { + "label" : "boolValue", + "name" : "boolValue", + "type" : { + "bool" : { + + } + } + }, + { + "label" : "stringValue", + "name" : "stringValue", + "type" : { + "string" : { + + } + } + }, + { + "label" : "jsObject", + "name" : "jsObject", + "type" : { + "jsObject" : { + + } + } + }, + { + "label" : "sibling", + "name" : "sibling", + "type" : { + "swiftHeapObject" : { + "_0" : "SimplePropertyHolder" + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_PropertyHolder_getAllValues", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getAllValues", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "PropertyHolder", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "intValue", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "floatValue", + "type" : { + "float" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "doubleValue", + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "boolValue", + "type" : { + "bool" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "stringValue", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "readonlyInt", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "readonlyFloat", + "type" : { + "float" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "readonlyDouble", + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "readonlyBool", + "type" : { + "bool" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "readonlyString", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "jsObject", + "type" : { + "jsObject" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "sibling", + "type" : { + "swiftHeapObject" : { + "_0" : "SimplePropertyHolder" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "lazyValue", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "computedReadonly", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "computedReadWrite", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "observedProperty", + "type" : { + "int" : { + + } + } + } + ], + "swiftCallName" : "PropertyHolder" + }, + { + "methods" : [ + { + "abiName" : "bjs_MathUtils_static_add", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "add", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "int" : { + + } + } + }, + { + "label" : "b", + "name" : "b", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "className" : { + "_0" : "MathUtils" + } + } + }, + { + "abiName" : "bjs_MathUtils_static_substract", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "substract", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "int" : { + + } + } + }, + { + "label" : "b", + "name" : "b", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "className" : { + "_0" : "MathUtils" + } + } + } + ], + "name" : "MathUtils", + "properties" : [ + + ], + "swiftCallName" : "MathUtils" + }, + { + "constructor" : { + "abiName" : "bjs_ConstructorDefaults_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "defaultValue" : { + "string" : { + "_0" : "Default" + } + }, + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "defaultValue" : { + "int" : { + "_0" : 42 + } + }, + "label" : "count", + "name" : "count", + "type" : { + "int" : { + + } + } + }, + { + "defaultValue" : { + "bool" : { + "_0" : true + } + }, + "label" : "enabled", + "name" : "enabled", + "type" : { + "bool" : { + + } + } + }, + { + "defaultValue" : { + "enumCase" : { + "_0" : "Status", + "_1" : "success" + } + }, + "label" : "status", + "name" : "status", + "type" : { + "caseEnum" : { + "_0" : "Status" + } + } + }, + { + "defaultValue" : { + "null" : { + + } + }, + "label" : "tag", + "name" : "tag", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_ConstructorDefaults_describe", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "describe", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "ConstructorDefaults", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "count", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "enabled", + "type" : { + "bool" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "status", + "type" : { + "caseEnum" : { + "_0" : "Status" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "tag", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "ConstructorDefaults" + }, + { + "constructor" : { + "abiName" : "bjs_StaticPropertyHolder_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + + ], + "name" : "StaticPropertyHolder", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : true, + "name" : "staticConstant", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "staticVariable", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "staticString", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "staticBool", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "bool" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "staticFloat", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "float" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "staticDouble", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "computedProperty", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "readOnlyComputed", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "optionalString", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "optionalInt", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "jsObjectProperty", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "jsObject" : { + + } + } + } + ], + "swiftCallName" : "StaticPropertyHolder" + }, + { + "constructor" : { + "abiName" : "bjs_DataProcessorManager_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "processor", + "name" : "processor", + "type" : { + "swiftProtocol" : { + "_0" : "DataProcessor" + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_DataProcessorManager_incrementByAmount", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "incrementByAmount", + "parameters" : [ + { + "label" : "_", + "name" : "amount", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_setProcessorLabel", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setProcessorLabel", + "parameters" : [ + { + "label" : "_", + "name" : "prefix", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "suffix", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_isProcessorEven", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "isProcessorEven", + "parameters" : [ + + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_getProcessorLabel", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getProcessorLabel", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_getCurrentValue", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getCurrentValue", + "parameters" : [ + + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_incrementBoth", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "incrementBoth", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_getBackupValue", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getBackupValue", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_hasBackup", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "hasBackup", + "parameters" : [ + + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_getProcessorOptionalTag", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getProcessorOptionalTag", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_setProcessorOptionalTag", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setProcessorOptionalTag", + "parameters" : [ + { + "label" : "_", + "name" : "tag", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_getProcessorOptionalCount", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getProcessorOptionalCount", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_setProcessorOptionalCount", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setProcessorOptionalCount", + "parameters" : [ + { + "label" : "_", + "name" : "count", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_getProcessorDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getProcessorDirection", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_setProcessorDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setProcessorDirection", + "parameters" : [ + { + "label" : "_", + "name" : "direction", + "type" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_getProcessorTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getProcessorTheme", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_setProcessorTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setProcessorTheme", + "parameters" : [ + { + "label" : "_", + "name" : "theme", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_getProcessorHttpStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getProcessorHttpStatus", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_setProcessorHttpStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setProcessorHttpStatus", + "parameters" : [ + { + "label" : "_", + "name" : "status", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_getProcessorAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getProcessorAPIResult", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_DataProcessorManager_setProcessorAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setProcessorAPIResult", + "parameters" : [ + { + "label" : "_", + "name" : "apiResult", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "DataProcessorManager", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "processor", + "type" : { + "swiftProtocol" : { + "_0" : "DataProcessor" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "backupProcessor", + "type" : { + "nullable" : { + "_0" : { + "swiftProtocol" : { + "_0" : "DataProcessor" + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "DataProcessorManager" + }, + { + "constructor" : { + "abiName" : "bjs_SwiftDataProcessor_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_SwiftDataProcessor_increment", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "increment", + "parameters" : [ + { + "label" : "by", + "name" : "amount", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_SwiftDataProcessor_getValue", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getValue", + "parameters" : [ + + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_SwiftDataProcessor_setLabelElements", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setLabelElements", + "parameters" : [ + { + "label" : "_", + "name" : "labelPrefix", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "labelSuffix", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_SwiftDataProcessor_getLabel", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getLabel", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_SwiftDataProcessor_isEven", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "isEven", + "parameters" : [ + + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_SwiftDataProcessor_processGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processGreeter", + "parameters" : [ + { + "label" : "_", + "name" : "greeter", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_SwiftDataProcessor_createGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createGreeter", + "parameters" : [ + + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "abiName" : "bjs_SwiftDataProcessor_processOptionalGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalGreeter", + "parameters" : [ + { + "label" : "_", + "name" : "greeter", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_SwiftDataProcessor_createOptionalGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createOptionalGreeter", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_SwiftDataProcessor_handleAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "handleAPIResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_SwiftDataProcessor_getAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getAPIResult", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + } + ], + "name" : "SwiftDataProcessor", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "count", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "optionalTag", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "optionalCount", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "direction", + "type" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "optionalTheme", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "httpStatus", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "apiResult", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "helper", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "optionalHelper", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "SwiftDataProcessor" + }, + { + "constructor" : { + "abiName" : "bjs_TextProcessor_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "transform", + "name" : "transform", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSS_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_TextProcessor_process", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "process", + "parameters" : [ + { + "label" : "_", + "name" : "text", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_TextProcessor_processWithCustom", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processWithCustom", + "parameters" : [ + { + "label" : "_", + "name" : "text", + "type" : { + "string" : { + + } + } + }, + { + "label" : "customTransform", + "name" : "customTransform", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSiSSSd_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "int" : { + + } + }, + { + "string" : { + + } + }, + { + "double" : { + + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_TextProcessor_getTransform", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getTransform", + "parameters" : [ + + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSS_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_TextProcessor_processOptionalString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalString", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSqSS_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_TextProcessor_processOptionalInt", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalInt", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSqSi_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_TextProcessor_processOptionalGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalGreeter", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSq7GreeterC_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_TextProcessor_makeOptionalStringFormatter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeOptionalStringFormatter", + "parameters" : [ + + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSqSS_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_TextProcessor_makeOptionalGreeterCreator", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeOptionalGreeterCreator", + "parameters" : [ + + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsy_Sq7GreeterC", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_TextProcessor_processDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processDirection", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTests9DirectionO_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "caseEnum" : { + "_0" : "Direction" + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_TextProcessor_processTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processTheme", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTests5ThemeO_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_TextProcessor_processHttpStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processHttpStatus", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTests10HttpStatusO_Si", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_TextProcessor_processAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processAPIResult", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTests9APIResultO_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_TextProcessor_makeDirectionChecker", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeDirectionChecker", + "parameters" : [ + + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTests9DirectionO_Sb", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "caseEnum" : { + "_0" : "Direction" + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_TextProcessor_makeThemeValidator", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeThemeValidator", + "parameters" : [ + + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTests5ThemeO_Sb", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_TextProcessor_makeStatusCodeExtractor", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeStatusCodeExtractor", + "parameters" : [ + + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTests10HttpStatusO_Si", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_TextProcessor_makeAPIResultHandler", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeAPIResultHandler", + "parameters" : [ + + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTests9APIResultO_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_TextProcessor_processOptionalDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalDirection", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSq9DirectionO_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_TextProcessor_processOptionalTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalTheme", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSq5ThemeO_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_TextProcessor_processOptionalAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalAPIResult", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSq9APIResultO_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_TextProcessor_makeOptionalDirectionFormatter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeOptionalDirectionFormatter", + "parameters" : [ + + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSq9DirectionO_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "name" : "TextProcessor", + "properties" : [ + + ], + "swiftCallName" : "TextProcessor" + }, + { + "constructor" : { + "abiName" : "bjs_OptionalHolder_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "nullableGreeter", + "name" : "nullableGreeter", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + }, + { + "label" : "undefinedNumber", + "name" : "undefinedNumber", + "type" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "undefined" + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "OptionalHolder", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "nullableGreeter", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "undefinedNumber", + "type" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "undefined" + } + } + } + ], + "swiftCallName" : "OptionalHolder" + }, + { + "constructor" : { + "abiName" : "bjs_OptionalPropertyHolder_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "optionalName", + "name" : "optionalName", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "OptionalPropertyHolder", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "optionalName", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "optionalAge", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "optionalGreeter", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "OptionalPropertyHolder" + }, + { + "constructor" : { + "abiName" : "bjs_Container_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "location", + "name" : "location", + "type" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + } + }, + { + "label" : "config", + "name" : "config", + "type" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Config" + } + }, + "_1" : "null" + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "Container", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "location", + "type" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + } + }, + { + "isReadonly" : false, + "isStatic" : false, + "name" : "config", + "type" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Config" + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "Container" + } + ], + "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" : "loading" + }, + { + "associatedValues" : [ + + ], + "name" : "success" + }, + { + "associatedValues" : [ + + ], + "name" : "error" + } + ], + "emitStyle" : "const", + "name" : "Status", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Status", + "tsFullPath" : "Status" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "light", + "rawValue" : "light" + }, + { + "associatedValues" : [ + + ], + "name" : "dark", + "rawValue" : "dark" + }, + { + "associatedValues" : [ + + ], + "name" : "auto", + "rawValue" : "auto" + } + ], + "emitStyle" : "const", + "name" : "Theme", + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Theme", + "tsFullPath" : "Theme" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "ok", + "rawValue" : "200" + }, + { + "associatedValues" : [ + + ], + "name" : "notFound", + "rawValue" : "404" + }, + { + "associatedValues" : [ + + ], + "name" : "serverError", + "rawValue" : "500" + }, + { + "associatedValues" : [ + + ], + "name" : "unknown", + "rawValue" : "-1" + } + ], + "emitStyle" : "const", + "name" : "HttpStatus", + "rawType" : "Int", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "HttpStatus", + "tsFullPath" : "HttpStatus" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "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" + }, + { + "associatedValues" : [ + + ], + "name" : "south" + }, + { + "associatedValues" : [ + + ], + "name" : "east" + }, + { + "associatedValues" : [ + + ], + "name" : "west" + } + ], + "emitStyle" : "tsEnum", + "name" : "TSDirection", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "TSDirection", + "tsFullPath" : "TSDirection" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "light", + "rawValue" : "light" + }, + { + "associatedValues" : [ + + ], + "name" : "dark", + "rawValue" : "dark" + }, + { + "associatedValues" : [ + + ], + "name" : "auto", + "rawValue" : "auto" + } + ], + "emitStyle" : "tsEnum", + "name" : "TSTheme", + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "TSTheme", + "tsFullPath" : "TSTheme" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Utils", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utils", + "tsFullPath" : "Utils" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "StringUtils", + "namespace" : [ + "Utils" + ], + "staticMethods" : [ + { + "abiName" : "bjs_Utils_StringUtils_static_uppercase", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "uppercase", + "namespace" : [ + "Utils", + "StringUtils" + ], + "parameters" : [ + { + "label" : "_", + "name" : "text", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "Utils.StringUtils" + } + } + }, + { + "abiName" : "bjs_Utils_StringUtils_static_lowercase", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "lowercase", + "namespace" : [ + "Utils", + "StringUtils" + ], + "parameters" : [ + { + "label" : "_", + "name" : "text", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "Utils.StringUtils" + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utils.StringUtils", + "tsFullPath" : "Utils.StringUtils" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Networking", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Networking", + "tsFullPath" : "Networking" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "API", + "namespace" : [ + "Networking" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Networking.API", + "tsFullPath" : "Networking.API" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "get" + }, + { + "associatedValues" : [ + + ], + "name" : "post" + }, + { + "associatedValues" : [ + + ], + "name" : "put" + }, + { + "associatedValues" : [ + + ], + "name" : "delete" + } + ], + "emitStyle" : "const", + "name" : "Method", + "namespace" : [ + "Networking", + "API" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Networking.API.Method", + "tsFullPath" : "Networking.API.Method" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Configuration", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Configuration", + "tsFullPath" : "Configuration" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "debug", + "rawValue" : "debug" + }, + { + "associatedValues" : [ + + ], + "name" : "info", + "rawValue" : "info" + }, + { + "associatedValues" : [ + + ], + "name" : "warning", + "rawValue" : "warning" + }, + { + "associatedValues" : [ + + ], + "name" : "error", + "rawValue" : "error" + } + ], + "emitStyle" : "const", + "name" : "LogLevel", + "namespace" : [ + "Configuration" + ], + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Configuration.LogLevel", + "tsFullPath" : "Configuration.LogLevel" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "http", + "rawValue" : "80" + }, + { + "associatedValues" : [ + + ], + "name" : "https", + "rawValue" : "443" + }, + { + "associatedValues" : [ + + ], + "name" : "development", + "rawValue" : "3000" + } + ], + "emitStyle" : "const", + "name" : "Port", + "namespace" : [ + "Configuration" + ], + "rawType" : "Int", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Configuration.Port", + "tsFullPath" : "Configuration.Port" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Internal", + "namespace" : [ + "Networking", + "APIV2" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Internal", + "tsFullPath" : "Networking.APIV2.Internal" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "get" + }, + { + "associatedValues" : [ + + ], + "name" : "post" + } + ], + "emitStyle" : "const", + "name" : "SupportedMethod", + "namespace" : [ + "Networking", + "APIV2", + "Internal" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Internal.SupportedMethod", + "tsFullPath" : "Networking.APIV2.Internal.SupportedMethod" + }, + { + "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" : [ + + ], + "name" : "info" + } + ], + "emitStyle" : "const", + "name" : "APIResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "APIResult", + "tsFullPath" : "APIResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "error" + }, + { + "associatedValues" : [ + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "location" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "status" + }, + { + "associatedValues" : [ + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + } + ], + "name" : "coordinates" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "comprehensive" + }, + { + "associatedValues" : [ + + ], + "name" : "info" + } + ], + "emitStyle" : "const", + "name" : "ComplexResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "ComplexResult", + "tsFullPath" : "ComplexResult" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Utilities", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utilities", + "tsFullPath" : "Utilities" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "status" + } + ], + "emitStyle" : "const", + "name" : "Result", + "namespace" : [ + "Utilities" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utilities.Result", + "tsFullPath" : "Utilities.Result" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "API", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "API", + "tsFullPath" : "API" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + } + ], + "emitStyle" : "const", + "name" : "NetworkingResult", + "namespace" : [ + "API" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "API.NetworkingResult", + "tsFullPath" : "API.NetworkingResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "swiftStruct" : { + "_0" : "Address" + } + } + } + ], + "name" : "structPayload" + }, + { + "associatedValues" : [ + { + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "name" : "classPayload" + }, + { + "associatedValues" : [ + { + "type" : { + "jsObject" : { + + } + } + } + ], + "name" : "jsObjectPayload" + }, + { + "associatedValues" : [ + { + "type" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + ], + "name" : "nestedEnum" + }, + { + "associatedValues" : [ + { + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "name" : "arrayPayload" + }, + { + "associatedValues" : [ + { + "type" : { + "jsObject" : { + "_0" : "Foo" + } + } + } + ], + "name" : "jsClassPayload" + }, + { + "associatedValues" : [ + + ], + "name" : "empty" + } + ], + "emitStyle" : "const", + "name" : "AllTypesResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "AllTypesResult", + "tsFullPath" : "AllTypesResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" + } + } + } + ], + "name" : "precision" + }, + { + "associatedValues" : [ + { + "type" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + ], + "name" : "direction" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" + } + }, + "_1" : "null" + } + } + } + ], + "name" : "optPrecision" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + } + ], + "name" : "optDirection" + }, + { + "associatedValues" : [ + + ], + "name" : "empty" + } + ], + "emitStyle" : "const", + "name" : "TypedPayloadResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "TypedPayloadResult", + "tsFullPath" : "TypedPayloadResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "scientific" + }, + { + "associatedValues" : [ + + ], + "name" : "basic" + } + ], + "emitStyle" : "const", + "name" : "StaticCalculator", + "staticMethods" : [ + { + "abiName" : "bjs_StaticCalculator_static_roundtrip", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "roundtrip", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "enumName" : { + "_0" : "StaticCalculator" + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "StaticCalculator", + "tsFullPath" : "StaticCalculator" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "StaticUtils", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "StaticUtils", + "tsFullPath" : "StaticUtils" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Nested", + "namespace" : [ + "StaticUtils" + ], + "staticMethods" : [ + { + "abiName" : "bjs_StaticUtils_Nested_static_roundtrip", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "roundtrip", + "namespace" : [ + "StaticUtils", + "Nested" + ], + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "StaticUtils.Nested" + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "StaticUtils.Nested", + "tsFullPath" : "StaticUtils.Nested" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "GraphOperations", + "namespace" : [ + "Services", + "Graph" + ], + "staticMethods" : [ + { + "abiName" : "bjs_Services_Graph_GraphOperations_static_createGraph", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "createGraph", + "namespace" : [ + "Services", + "Graph", + "GraphOperations" + ], + "parameters" : [ + { + "label" : "rootId", + "name" : "rootId", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "GraphOperations" + } + } + }, + { + "abiName" : "bjs_Services_Graph_GraphOperations_static_nodeCount", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "nodeCount", + "namespace" : [ + "Services", + "Graph", + "GraphOperations" + ], + "parameters" : [ + { + "label" : "graphId", + "name" : "graphId", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "GraphOperations" + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "GraphOperations", + "tsFullPath" : "Services.Graph.GraphOperations" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "option1" + }, + { + "associatedValues" : [ + + ], + "name" : "option2" + } + ], + "emitStyle" : "const", + "name" : "StaticPropertyEnum", + "staticMethods" : [ + + ], + "staticProperties" : [ + { + "isReadonly" : false, + "isStatic" : true, + "name" : "enumProperty", + "staticContext" : { + "enumName" : { + "_0" : "StaticPropertyEnum" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "enumConstant", + "staticContext" : { + "enumName" : { + "_0" : "StaticPropertyEnum" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "enumBool", + "staticContext" : { + "enumName" : { + "_0" : "StaticPropertyEnum" + } + }, + "type" : { + "bool" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "enumVariable", + "staticContext" : { + "enumName" : { + "_0" : "StaticPropertyEnum" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "computedReadonly", + "staticContext" : { + "enumName" : { + "_0" : "StaticPropertyEnum" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "computedReadWrite", + "staticContext" : { + "enumName" : { + "_0" : "StaticPropertyEnum" + } + }, + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "StaticPropertyEnum", + "tsFullPath" : "StaticPropertyEnum" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "StaticPropertyNamespace", + "staticMethods" : [ + + ], + "staticProperties" : [ + { + "isReadonly" : false, + "isStatic" : true, + "name" : "namespaceProperty", + "namespace" : [ + "StaticPropertyNamespace" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "StaticPropertyNamespace" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "namespaceConstant", + "namespace" : [ + "StaticPropertyNamespace" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "StaticPropertyNamespace" + } + }, + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "StaticPropertyNamespace", + "tsFullPath" : "StaticPropertyNamespace" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "NestedProperties", + "namespace" : [ + "StaticPropertyNamespace" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + { + "isReadonly" : false, + "isStatic" : true, + "name" : "nestedProperty", + "namespace" : [ + "StaticPropertyNamespace", + "NestedProperties" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "StaticPropertyNamespace.NestedProperties" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "nestedConstant", + "namespace" : [ + "StaticPropertyNamespace", + "NestedProperties" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "StaticPropertyNamespace.NestedProperties" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "nestedDouble", + "namespace" : [ + "StaticPropertyNamespace", + "NestedProperties" + ], + "staticContext" : { + "namespaceEnum" : { + "_0" : "StaticPropertyNamespace.NestedProperties" + } + }, + "type" : { + "double" : { + + } + } + } + ], + "swiftCallName" : "StaticPropertyNamespace.NestedProperties", + "tsFullPath" : "StaticPropertyNamespace.NestedProperties" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Address" + } + }, + "_1" : "null" + } + } + } + ], + "name" : "optStruct" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ], + "name" : "optClass" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "jsObject" : { + + } + }, + "_1" : "null" + } + } + } + ], + "name" : "optJSObject" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + } + ], + "name" : "optNestedEnum" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "name" : "optArray" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "jsObject" : { + "_0" : "Foo" + } + }, + "_1" : "null" + } + } + } + ], + "name" : "optJsClass" + }, + { + "associatedValues" : [ + + ], + "name" : "empty" + } + ], + "emitStyle" : "const", + "name" : "OptionalAllTypesResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "OptionalAllTypesResult", + "tsFullPath" : "OptionalAllTypesResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + { + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + }, + { + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "name" : "status" + } + ], + "emitStyle" : "const", + "name" : "APIOptionalResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "APIOptionalResult", + "tsFullPath" : "APIOptionalResult" + } + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_roundTripVoid", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripVoid", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_roundTripInt", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripInt", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "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" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripFloat", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "float" : { + + } + } + } + ], + "returnType" : { + "float" : { + + } + } + }, + { + "abiName" : "bjs_roundTripDouble", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripDouble", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + { + "abiName" : "bjs_roundTripBool", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripBool", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_roundTripString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripString", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_roundTripSwiftHeapObject", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripSwiftHeapObject", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "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" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripJSObject", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "jsObject" : { + + } + } + } + ], + "returnType" : { + "jsObject" : { + + } + } + }, + { + "abiName" : "bjs_roundTripDictionaryExport", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripDictionaryExport", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "dictionary" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalDictionaryExport", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalDictionaryExport", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "dictionary" : { + "_0" : { + "string" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "dictionary" : { + "_0" : { + "string" : { + + } + } + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripJSValue", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripJSValue", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "jsValue" : { + + } + } + } + ], + "returnType" : { + "jsValue" : { + + } + } + }, + { + "abiName" : "bjs_roundTripOptionalJSValue", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalJSValue", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "jsValue" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "jsValue" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripJSValueArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripJSValueArray", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalJSValueArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalJSValueArray", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_makeImportedFoo", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "makeImportedFoo", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "jsObject" : { + "_0" : "Foo" + } + } + }, + { + "abiName" : "bjs_throwsSwiftError", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "throwsSwiftError", + "parameters" : [ + { + "label" : "shouldThrow", + "name" : "shouldThrow", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_throwsWithIntResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "throwsWithIntResult", + "parameters" : [ + + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_throwsWithStringResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "throwsWithStringResult", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_throwsWithBoolResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "throwsWithBoolResult", + "parameters" : [ + + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_throwsWithFloatResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "throwsWithFloatResult", + "parameters" : [ + + ], + "returnType" : { + "float" : { + + } + } + }, + { + "abiName" : "bjs_throwsWithDoubleResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "throwsWithDoubleResult", + "parameters" : [ + + ], + "returnType" : { + "double" : { + + } + } + }, + { + "abiName" : "bjs_throwsWithSwiftHeapObjectResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "throwsWithSwiftHeapObjectResult", + "parameters" : [ + + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "abiName" : "bjs_throwsWithJSObjectResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "throwsWithJSObjectResult", + "parameters" : [ + + ], + "returnType" : { + "jsObject" : { + + } + } + }, + { + "abiName" : "bjs_asyncRoundTripVoid", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripVoid", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_asyncRoundTripInt", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripInt", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_asyncRoundTripFloat", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripFloat", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "float" : { + + } + } + } + ], + "returnType" : { + "float" : { + + } + } + }, + { + "abiName" : "bjs_asyncRoundTripDouble", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripDouble", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + { + "abiName" : "bjs_asyncRoundTripBool", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripBool", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_asyncRoundTripString", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripString", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_asyncRoundTripSwiftHeapObject", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripSwiftHeapObject", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripJSObject", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripJSObject", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "jsObject" : { + + } + } + } + ], + "returnType" : { + "jsObject" : { + + } + } + }, + { + "abiName" : "bjs_takeGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeGreeter", + "parameters" : [ + { + "label" : "g", + "name" : "g", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_createCalculator", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createCalculator", + "parameters" : [ + + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Calculator" + } + } + }, + { + "abiName" : "bjs_useCalculator", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "useCalculator", + "parameters" : [ + { + "label" : "calc", + "name" : "calc", + "type" : { + "swiftHeapObject" : { + "_0" : "Calculator" + } + } + }, + { + "label" : "x", + "name" : "x", + "type" : { + "int" : { + + } + } + }, + { + "label" : "y", + "name" : "y", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_testGreeterToJSValue", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testGreeterToJSValue", + "parameters" : [ + + ], + "returnType" : { + "jsObject" : { + + } + } + }, + { + "abiName" : "bjs_testCalculatorToJSValue", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testCalculatorToJSValue", + "parameters" : [ + + ], + "returnType" : { + "jsObject" : { + + } + } + }, + { + "abiName" : "bjs_testSwiftClassAsJSValue", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testSwiftClassAsJSValue", + "parameters" : [ + { + "label" : "greeter", + "name" : "greeter", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "returnType" : { + "jsObject" : { + + } + } + }, + { + "abiName" : "bjs_setDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setDirection", + "parameters" : [ + { + "label" : "_", + "name" : "direction", + "type" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "Direction" + } + } + }, + { + "abiName" : "bjs_getDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getDirection", + "parameters" : [ + + ], + "returnType" : { + "caseEnum" : { + "_0" : "Direction" + } + } + }, + { + "abiName" : "bjs_processDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processDirection", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "Status" + } + } + }, + { + "abiName" : "bjs_setTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setTheme", + "parameters" : [ + { + "label" : "_", + "name" : "theme", + "type" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + }, + { + "abiName" : "bjs_getTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getTheme", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + }, + { + "abiName" : "bjs_setHttpStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setHttpStatus", + "parameters" : [ + { + "label" : "_", + "name" : "status", + "type" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + }, + { + "abiName" : "bjs_getHttpStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getHttpStatus", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + }, + { + "abiName" : "bjs_processTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processTheme", + "parameters" : [ + { + "label" : "_", + "name" : "theme", + "type" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + }, + { + "abiName" : "bjs_setTSDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setTSDirection", + "parameters" : [ + { + "label" : "_", + "name" : "direction", + "type" : { + "caseEnum" : { + "_0" : "TSDirection" + } + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "TSDirection" + } + } + }, + { + "abiName" : "bjs_getTSDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getTSDirection", + "parameters" : [ + + ], + "returnType" : { + "caseEnum" : { + "_0" : "TSDirection" + } + } + }, + { + "abiName" : "bjs_setTSTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setTSTheme", + "parameters" : [ + { + "label" : "_", + "name" : "theme", + "type" : { + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" + } + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" + } + } + }, + { + "abiName" : "bjs_getTSTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getTSTheme", + "parameters" : [ + + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" + } + } + }, + { + "abiName" : "bjs_roundtripNetworkingAPIMethod", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripNetworkingAPIMethod", + "parameters" : [ + { + "label" : "_", + "name" : "method", + "type" : { + "caseEnum" : { + "_0" : "Networking.API.Method" + } + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "Networking.API.Method" + } + } + }, + { + "abiName" : "bjs_roundtripConfigurationLogLevel", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripConfigurationLogLevel", + "parameters" : [ + { + "label" : "_", + "name" : "level", + "type" : { + "rawValueEnum" : { + "_0" : "Configuration.LogLevel", + "_1" : "String" + } + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Configuration.LogLevel", + "_1" : "String" + } + } + }, + { + "abiName" : "bjs_roundtripConfigurationPort", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripConfigurationPort", + "parameters" : [ + { + "label" : "_", + "name" : "port", + "type" : { + "rawValueEnum" : { + "_0" : "Configuration.Port", + "_1" : "Int" + } + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Configuration.Port", + "_1" : "Int" + } + } + }, + { + "abiName" : "bjs_processConfigurationLogLevel", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processConfigurationLogLevel", + "parameters" : [ + { + "label" : "_", + "name" : "level", + "type" : { + "rawValueEnum" : { + "_0" : "Configuration.LogLevel", + "_1" : "String" + } + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Configuration.Port", + "_1" : "Int" + } + } + }, + { + "abiName" : "bjs_roundtripInternalSupportedMethod", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripInternalSupportedMethod", + "parameters" : [ + { + "label" : "_", + "name" : "method", + "type" : { + "caseEnum" : { + "_0" : "Internal.SupportedMethod" + } + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "Internal.SupportedMethod" + } + } + }, + { + "abiName" : "bjs_roundtripAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripAPIResult", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_makeAPIResultSuccess", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeAPIResultSuccess", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_makeAPIResultFailure", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeAPIResultFailure", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_makeAPIResultInfo", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeAPIResultInfo", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_makeAPIResultFlag", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeAPIResultFlag", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_makeAPIResultRate", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeAPIResultRate", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "float" : { + + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_makeAPIResultPrecise", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeAPIResultPrecise", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_roundtripComplexResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripComplexResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_makeComplexResultSuccess", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeComplexResultSuccess", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_makeComplexResultError", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeComplexResultError", + "parameters" : [ + { + "label" : "_", + "name" : "message", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "code", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_makeComplexResultLocation", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeComplexResultLocation", + "parameters" : [ + { + "label" : "_", + "name" : "lat", + "type" : { + "double" : { + + } + } + }, + { + "label" : "_", + "name" : "lng", + "type" : { + "double" : { + + } + } + }, + { + "label" : "_", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_makeComplexResultStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeComplexResultStatus", + "parameters" : [ + { + "label" : "_", + "name" : "active", + "type" : { + "bool" : { + + } + } + }, + { + "label" : "_", + "name" : "code", + "type" : { + "int" : { + + } + } + }, + { + "label" : "_", + "name" : "message", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_makeComplexResultCoordinates", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeComplexResultCoordinates", + "parameters" : [ + { + "label" : "_", + "name" : "x", + "type" : { + "double" : { + + } + } + }, + { + "label" : "_", + "name" : "y", + "type" : { + "double" : { + + } + } + }, + { + "label" : "_", + "name" : "z", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_makeComplexResultComprehensive", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeComplexResultComprehensive", + "parameters" : [ + { + "label" : "_", + "name" : "flag1", + "type" : { + "bool" : { + + } + } + }, + { + "label" : "_", + "name" : "flag2", + "type" : { + "bool" : { + + } + } + }, + { + "label" : "_", + "name" : "count1", + "type" : { + "int" : { + + } + } + }, + { + "label" : "_", + "name" : "count2", + "type" : { + "int" : { + + } + } + }, + { + "label" : "_", + "name" : "value1", + "type" : { + "double" : { + + } + } + }, + { + "label" : "_", + "name" : "value2", + "type" : { + "double" : { + + } + } + }, + { + "label" : "_", + "name" : "text1", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "text2", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "text3", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_makeComplexResultInfo", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeComplexResultInfo", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_makeUtilitiesResultSuccess", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeUtilitiesResultSuccess", + "parameters" : [ + { + "label" : "_", + "name" : "message", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "Utilities.Result" + } + } + }, + { + "abiName" : "bjs_makeUtilitiesResultFailure", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeUtilitiesResultFailure", + "parameters" : [ + { + "label" : "_", + "name" : "error", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "code", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "Utilities.Result" + } + } + }, + { + "abiName" : "bjs_makeUtilitiesResultStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeUtilitiesResultStatus", + "parameters" : [ + { + "label" : "_", + "name" : "active", + "type" : { + "bool" : { + + } + } + }, + { + "label" : "_", + "name" : "code", + "type" : { + "int" : { + + } + } + }, + { + "label" : "_", + "name" : "message", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "Utilities.Result" + } + } + }, + { + "abiName" : "bjs_makeAPINetworkingResultSuccess", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeAPINetworkingResultSuccess", + "parameters" : [ + { + "label" : "_", + "name" : "message", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "API.NetworkingResult" + } + } + }, + { + "abiName" : "bjs_makeAPINetworkingResultFailure", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeAPINetworkingResultFailure", + "parameters" : [ + { + "label" : "_", + "name" : "error", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "code", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "API.NetworkingResult" + } + } + }, + { + "abiName" : "bjs_roundtripUtilitiesResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripUtilitiesResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "Utilities.Result" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "Utilities.Result" + } + } + }, + { + "abiName" : "bjs_roundtripAPINetworkingResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripAPINetworkingResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "API.NetworkingResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "API.NetworkingResult" + } + } + }, + { + "abiName" : "bjs_roundTripAllTypesResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripAllTypesResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "AllTypesResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "AllTypesResult" + } + } + }, + { + "abiName" : "bjs_roundTripTypedPayloadResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripTypedPayloadResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "TypedPayloadResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "TypedPayloadResult" + } + } + }, + { + "abiName" : "bjs_createPropertyHolder", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createPropertyHolder", + "parameters" : [ + { + "label" : "intValue", + "name" : "intValue", + "type" : { + "int" : { + + } + } + }, + { + "label" : "floatValue", + "name" : "floatValue", + "type" : { + "float" : { + + } + } + }, + { + "label" : "doubleValue", + "name" : "doubleValue", + "type" : { + "double" : { + + } + } + }, + { + "label" : "boolValue", + "name" : "boolValue", + "type" : { + "bool" : { + + } + } + }, + { + "label" : "stringValue", + "name" : "stringValue", + "type" : { + "string" : { + + } + } + }, + { + "label" : "jsObject", + "name" : "jsObject", + "type" : { + "jsObject" : { + + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "PropertyHolder" + } + } + }, + { + "abiName" : "bjs_testPropertyHolder", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testPropertyHolder", + "parameters" : [ + { + "label" : "holder", + "name" : "holder", + "type" : { + "swiftHeapObject" : { + "_0" : "PropertyHolder" + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_resetObserverCounts", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "resetObserverCounts", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getObserverStats", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getObserverStats", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_testStringDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testStringDefault", + "parameters" : [ + { + "defaultValue" : { + "string" : { + "_0" : "Hello World" + } + }, + "label" : "message", + "name" : "message", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_testIntDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testIntDefault", + "parameters" : [ + { + "defaultValue" : { + "int" : { + "_0" : 42 + } + }, + "label" : "count", + "name" : "count", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_testBoolDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testBoolDefault", + "parameters" : [ + { + "defaultValue" : { + "bool" : { + "_0" : true + } + }, + "label" : "flag", + "name" : "flag", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_testOptionalDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testOptionalDefault", + "parameters" : [ + { + "defaultValue" : { + "null" : { + + } + }, + "label" : "name", + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_testMultipleDefaults", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testMultipleDefaults", + "parameters" : [ + { + "defaultValue" : { + "string" : { + "_0" : "Default Title" + } + }, + "label" : "title", + "name" : "title", + "type" : { + "string" : { + + } + } + }, + { + "defaultValue" : { + "int" : { + "_0" : -10 + } + }, + "label" : "count", + "name" : "count", + "type" : { + "int" : { + + } + } + }, + { + "defaultValue" : { + "bool" : { + "_0" : false + } + }, + "label" : "enabled", + "name" : "enabled", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_testSimpleEnumDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testSimpleEnumDefault", + "parameters" : [ + { + "defaultValue" : { + "enumCase" : { + "_0" : "Status", + "_1" : "success" + } + }, + "label" : "status", + "name" : "status", + "type" : { + "caseEnum" : { + "_0" : "Status" + } + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "Status" + } + } + }, + { + "abiName" : "bjs_testDirectionDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testDirectionDefault", + "parameters" : [ + { + "defaultValue" : { + "enumCase" : { + "_0" : "Direction", + "_1" : "north" + } + }, + "label" : "direction", + "name" : "direction", + "type" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "Direction" + } + } + }, + { + "abiName" : "bjs_testRawStringEnumDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testRawStringEnumDefault", + "parameters" : [ + { + "defaultValue" : { + "enumCase" : { + "_0" : "Theme", + "_1" : "light" + } + }, + "label" : "theme", + "name" : "theme", + "type" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + }, + { + "abiName" : "bjs_testComplexInit", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testComplexInit", + "parameters" : [ + { + "defaultValue" : { + "objectWithArguments" : { + "_0" : "Greeter", + "_1" : [ + { + "string" : { + "_0" : "DefaultGreeter" + } + } + ] + } + }, + "label" : "greeter", + "name" : "greeter", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_testEmptyInit", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testEmptyInit", + "parameters" : [ + { + "defaultValue" : { + "object" : { + "_0" : "StaticPropertyHolder" + } + }, + "label" : "_", + "name" : "object", + "type" : { + "swiftHeapObject" : { + "_0" : "StaticPropertyHolder" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "StaticPropertyHolder" + } + } + }, + { + "abiName" : "bjs_arrayWithDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "arrayWithDefault", + "parameters" : [ + { + "defaultValue" : { + "array" : { + "_0" : [ + { + "int" : { + "_0" : 1 + } + }, + { + "int" : { + "_0" : 2 + } + }, + { + "int" : { + "_0" : 3 + } + } + ] + } + }, + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_arrayWithOptionalDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "arrayWithOptionalDefault", + "parameters" : [ + { + "defaultValue" : { + "null" : { + + } + }, + "label" : "_", + "name" : "values", + "type" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "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" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "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", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "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" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "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" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalStringArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalStringArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalDataPointArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalDataPointArray", + "parameters" : [ + { + "label" : "_", + "name" : "points", + "type" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalDirectionArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalDirectionArray", + "parameters" : [ + { + "label" : "_", + "name" : "directions", + "type" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalStatusArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalStatusArray", + "parameters" : [ + { + "label" : "_", + "name" : "statuses", + "type" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Status" + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Status" + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalIntArrayType", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalIntArrayType", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalStringArrayType", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalStringArrayType", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalGreeterArrayType", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalGreeterArrayType", + "parameters" : [ + { + "label" : "_", + "name" : "greeters", + "type" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + }, + "_1" : "null" + } + } + }, + { + "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_roundTripUnsafePointerArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripUnsafePointerArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafePointer", + "pointee" : "UInt8" + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafePointer", + "pointee" : "UInt8" + } + } + } + } + } + }, + { + "abiName" : "bjs_roundTripUnsafeMutablePointerArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripUnsafeMutablePointerArray", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutablePointer", + "pointee" : "UInt8" + } + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutablePointer", + "pointee" : "UInt8" + } + } + } + } + } + }, + { + "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_roundTripJSObjectArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripJSObjectArray", + "parameters" : [ + { + "label" : "_", + "name" : "objects", + "type" : { + "array" : { + "_0" : { + "jsObject" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "jsObject" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalJSObjectArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalJSObjectArray", + "parameters" : [ + { + "label" : "_", + "name" : "objects", + "type" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "jsObject" : { + + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "jsObject" : { + + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripFooArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripFooArray", + "parameters" : [ + { + "label" : "_", + "name" : "foos", + "type" : { + "array" : { + "_0" : { + "jsObject" : { + "_0" : "Foo" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "jsObject" : { + "_0" : "Foo" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalFooArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalFooArray", + "parameters" : [ + { + "label" : "_", + "name" : "foos", + "type" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "jsObject" : { + "_0" : "Foo" + } + }, + "_1" : "null" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "jsObject" : { + "_0" : "Foo" + } + }, + "_1" : "null" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalString", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalInt", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalInt", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalBool", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalBool", + "parameters" : [ + { + "label" : "flag", + "name" : "flag", + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalFloat", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalFloat", + "parameters" : [ + { + "label" : "number", + "name" : "number", + "type" : { + "nullable" : { + "_0" : { + "float" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "float" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalDouble", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalDouble", + "parameters" : [ + { + "label" : "precision", + "name" : "precision", + "type" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalSyntax", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalSyntax", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalMixSyntax", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalMixSyntax", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalSwiftSyntax", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalSwiftSyntax", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalWithSpaces", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalWithSpaces", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalTypeAlias", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTypeAlias", + "parameters" : [ + { + "label" : "age", + "name" : "age", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalStatus", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Status" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Status" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTheme", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalHttpStatus", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalHttpStatus", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalTSDirection", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTSDirection", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "TSDirection" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "TSDirection" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalTSTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTSTheme", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalNetworkingAPIMethod", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalNetworkingAPIMethod", + "parameters" : [ + { + "label" : "_", + "name" : "method", + "type" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Networking.API.Method" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Networking.API.Method" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalAPIResult", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalTypedPayloadResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTypedPayloadResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "TypedPayloadResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "TypedPayloadResult" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_takeOptionalJSObject", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "takeOptionalJSObject", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "jsObject" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_compareAPIResults", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "compareAPIResults", + "parameters" : [ + { + "label" : "_", + "name" : "r1", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + }, + { + "label" : "_", + "name" : "r2", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_roundTripOptionalComplexResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalComplexResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalAllTypesResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalAllTypesResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "AllTypesResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "AllTypesResult" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalPayloadResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalPayloadResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "OptionalAllTypesResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "OptionalAllTypesResult" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalPayloadResultOpt", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalPayloadResultOpt", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "OptionalAllTypesResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "OptionalAllTypesResult" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalClass", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalClass", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalGreeter", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_applyOptionalGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "applyOptionalGreeter", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + }, + { + "label" : "_", + "name" : "transform", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSq7GreeterC_Sq7GreeterC", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_makeOptionalHolder", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeOptionalHolder", + "parameters" : [ + { + "label" : "nullableGreeter", + "name" : "nullableGreeter", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + }, + { + "label" : "undefinedNumber", + "name" : "undefinedNumber", + "type" : { + "nullable" : { + "_0" : { + "double" : { + + } + }, + "_1" : "undefined" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "OptionalHolder" + } + } + }, + { + "abiName" : "bjs_roundTripOptionalAPIOptionalResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalAPIOptionalResult", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIOptionalResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIOptionalResult" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripPointerFields", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripPointerFields", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftStruct" : { + "_0" : "PointerFields" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "PointerFields" + } + } + }, + { + "abiName" : "bjs_testStructDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testStructDefault", + "parameters" : [ + { + "defaultValue" : { + "structLiteral" : { + "_0" : "DataPoint", + "_1" : [ + { + "name" : "x", + "value" : { + "float" : { + "_0" : 1 + } + } + }, + { + "name" : "y", + "value" : { + "float" : { + "_0" : 2 + } + } + }, + { + "name" : "label", + "value" : { + "string" : { + "_0" : "default" + } + } + }, + { + "name" : "optCount", + "value" : { + "null" : { + + } + } + }, + { + "name" : "optFlag", + "value" : { + "null" : { + + } + } + } + ] + } + }, + "label" : "point", + "name" : "point", + "type" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "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" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripDataPoint", + "parameters" : [ + { + "label" : "_", + "name" : "data", + "type" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + } + }, + { + "abiName" : "bjs_roundTripPublicPoint", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripPublicPoint", + "parameters" : [ + { + "label" : "_", + "name" : "point", + "type" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } + }, + { + "abiName" : "bjs_roundTripContact", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripContact", + "parameters" : [ + { + "label" : "_", + "name" : "contact", + "type" : { + "swiftStruct" : { + "_0" : "Contact" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Contact" + } + } + }, + { + "abiName" : "bjs_roundTripConfig", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripConfig", + "parameters" : [ + { + "label" : "_", + "name" : "config", + "type" : { + "swiftStruct" : { + "_0" : "Config" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Config" + } + } + }, + { + "abiName" : "bjs_roundTripSessionData", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripSessionData", + "parameters" : [ + { + "label" : "_", + "name" : "session", + "type" : { + "swiftStruct" : { + "_0" : "SessionData" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "SessionData" + } + } + }, + { + "abiName" : "bjs_roundTripValidationReport", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripValidationReport", + "parameters" : [ + { + "label" : "_", + "name" : "report", + "type" : { + "swiftStruct" : { + "_0" : "ValidationReport" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "ValidationReport" + } + } + }, + { + "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" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "updateValidationReport", + "parameters" : [ + { + "label" : "_", + "name" : "newResult", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + }, + { + "label" : "_", + "name" : "report", + "type" : { + "swiftStruct" : { + "_0" : "ValidationReport" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "ValidationReport" + } + } + }, + { + "abiName" : "bjs_testContainerWithStruct", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testContainerWithStruct", + "parameters" : [ + { + "label" : "_", + "name" : "point", + "type" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Container" + } + } + }, + { + "abiName" : "bjs_roundTripJSObjectContainer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripJSObjectContainer", + "parameters" : [ + { + "label" : "_", + "name" : "container", + "type" : { + "swiftStruct" : { + "_0" : "JSObjectContainer" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "JSObjectContainer" + } + } + }, + { + "abiName" : "bjs_roundTripFooContainer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripFooContainer", + "parameters" : [ + { + "label" : "_", + "name" : "container", + "type" : { + "swiftStruct" : { + "_0" : "FooContainer" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "FooContainer" + } + } + }, + { + "abiName" : "bjs_roundTripArrayMembers", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripArrayMembers", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftStruct" : { + "_0" : "ArrayMembers" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "ArrayMembers" + } + } + }, + { + "abiName" : "bjs_arrayMembersSum", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "arrayMembersSum", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftStruct" : { + "_0" : "ArrayMembers" + } + } + }, + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_arrayMembersFirst", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "arrayMembersFirst", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftStruct" : { + "_0" : "ArrayMembers" + } + } + }, + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "protocols" : [ + { + "methods" : [ + { + "abiName" : "bjs_DataProcessor_increment", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "increment", + "parameters" : [ + { + "label" : "by", + "name" : "amount", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessor_getValue", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getValue", + "parameters" : [ + + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessor_setLabelElements", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setLabelElements", + "parameters" : [ + { + "label" : "_", + "name" : "labelPrefix", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "labelSuffix", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessor_getLabel", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getLabel", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessor_isEven", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "isEven", + "parameters" : [ + + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessor_processGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processGreeter", + "parameters" : [ + { + "label" : "_", + "name" : "greeter", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessor_createGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createGreeter", + "parameters" : [ + + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "abiName" : "bjs_DataProcessor_processOptionalGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalGreeter", + "parameters" : [ + { + "label" : "_", + "name" : "greeter", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessor_createOptionalGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createOptionalGreeter", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_DataProcessor_handleAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "handleAPIResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessor_getAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getAPIResult", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + } + ], + "name" : "DataProcessor", + "properties" : [ + { + "isReadonly" : false, + "name" : "count", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "name" : "optionalTag", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "name" : "optionalCount", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "name" : "direction", + "type" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "name" : "optionalTheme", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "name" : "httpStatus", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "name" : "apiResult", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "name" : "helper", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "isReadonly" : false, + "name" : "optionalHelper", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ] + } + ], + "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" : { + "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" + }, + { + "constructor" : { + "abiName" : "bjs_DataPoint_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "x", + "name" : "x", + "type" : { + "double" : { + + } + } + }, + { + "label" : "y", + "name" : "y", + "type" : { + "double" : { + + } + } + }, + { + "label" : "label", + "name" : "label", + "type" : { + "string" : { + + } + } + }, + { + "label" : "optCount", + "name" : "optCount", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "label" : "optFlag", + "name" : "optFlag", + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "DataPoint", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "x", + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "y", + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "label", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "optCount", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "optFlag", + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "DataPoint" + }, + { + "constructor" : { + "abiName" : "bjs_PublicPoint_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "x", + "name" : "x", + "type" : { + "int" : { + + } + } + }, + { + "label" : "y", + "name" : "y", + "type" : { + "int" : { + + } + } + } + ] + }, + "explicitAccessControl" : "public", + "methods" : [ + + ], + "name" : "PublicPoint", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "x", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "y", + "type" : { + "int" : { + + } + } + } + ], + "swiftCallName" : "PublicPoint" + }, + { + "methods" : [ + + ], + "name" : "Address", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "street", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "city", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "zipCode", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + ], + "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" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "secondaryAddress", + "type" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Address" + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "Contact" + }, + { + "methods" : [ + + ], + "name" : "Config", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "theme", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "direction", + "type" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + }, + { + "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" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ], + "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" : "status", + "type" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Status" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "outcome", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "ValidationReport" + }, + { + "methods" : [ + + ], + "name" : "AdvancedConfig", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "id", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "title", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "enabled", + "type" : { + "bool" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "theme", + "type" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "status", + "type" : { + "caseEnum" : { + "_0" : "Status" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "metadata", + "type" : { + "nullable" : { + "_0" : { + "jsObject" : { + + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "location", + "type" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "defaults", + "type" : { + "swiftStruct" : { + "_0" : "ConfigStruct" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "overrideDefaults", + "type" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "ConfigStruct" + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "AdvancedConfig" + }, + { + "methods" : [ + + ], + "name" : "MeasurementConfig", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "precision", + "type" : { + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "ratio", + "type" : { + "rawValueEnum" : { + "_0" : "Ratio", + "_1" : "Double" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "optionalPrecision", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "optionalRatio", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Ratio", + "_1" : "Double" + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "MeasurementConfig" + }, + { + "constructor" : { + "abiName" : "bjs_MathOperations_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "defaultValue" : { + "double" : { + "_0" : 0 + } + }, + "label" : "baseValue", + "name" : "baseValue", + "type" : { + "double" : { + + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_MathOperations_add", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "add", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "double" : { + + } + } + }, + { + "defaultValue" : { + "double" : { + "_0" : 10 + } + }, + "label" : "b", + "name" : "b", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + { + "abiName" : "bjs_MathOperations_multiply", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "multiply", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "double" : { + + } + } + }, + { + "label" : "b", + "name" : "b", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + { + "abiName" : "bjs_MathOperations_static_subtract", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "subtract", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "double" : { + + } + } + }, + { + "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" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "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" : { + "jsObject" : { + + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "CopyableNestedCart" + } + }, + "staticContext" : { + "structName" : { + "_0" : "CopyableNestedCart" + } + } + } + ], + "name" : "CopyableNestedCart", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "id", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "item", + "type" : { + "swiftStruct" : { + "_0" : "CopyableCartItem" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "shippingAddress", + "type" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Address" + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "CopyableNestedCart" + }, + { + "methods" : [ + + ], + "name" : "ConfigStruct", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "value", + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "defaultConfig", + "staticContext" : { + "structName" : { + "_0" : "ConfigStruct" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "maxRetries", + "staticContext" : { + "structName" : { + "_0" : "ConfigStruct" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "timeout", + "staticContext" : { + "structName" : { + "_0" : "ConfigStruct" + } + }, + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "computedSetting", + "staticContext" : { + "structName" : { + "_0" : "ConfigStruct" + } + }, + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "ConfigStruct" + }, + { + "methods" : [ + + ], + "name" : "JSObjectContainer", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "object", + "type" : { + "jsObject" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "optionalObject", + "type" : { + "nullable" : { + "_0" : { + "jsObject" : { + + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "JSObjectContainer" + }, + { + "methods" : [ + + ], + "name" : "FooContainer", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "foo", + "type" : { + "jsObject" : { + "_0" : "Foo" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "optionalFoo", + "type" : { + "nullable" : { + "_0" : { + "jsObject" : { + "_0" : "Foo" + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "FooContainer" + }, + { + "methods" : [ + { + "abiName" : "bjs_ArrayMembers_sumValues", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "sumValues", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_ArrayMembers_firstString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "firstString", + "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "name" : "ArrayMembers", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "ints", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "optStrings", + "type" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "swiftCallName" : "ArrayMembers" + } + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + + ], + "types" : [ + { + "getters" : [ + + ], + "methods" : [ + + ], + "name" : "ClosureSupportImports", + "setters" : [ + + ], + "staticMethods" : [ + { + "name" : "jsApplyVoid", + "parameters" : [ + { + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsy_y", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "jsApplyBool", + "parameters" : [ + { + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsy_Sb", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + + ], + "returnType" : { + "bool" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "name" : "jsApplyInt", + "parameters" : [ + { + "name" : "value", + "type" : { + "int" : { + + } + } + }, + { + "name" : "transform", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSi_Si", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "int" : { + + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "name" : "jsApplyDouble", + "parameters" : [ + { + "name" : "value", + "type" : { + "double" : { + + } + } + }, + { + "name" : "transform", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSd_Sd", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "double" : { + + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + { + "name" : "jsApplyString", + "parameters" : [ + { + "name" : "value", + "type" : { + "string" : { + + } + } + }, + { + "name" : "transform", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSS_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "name" : "jsApplyJSObject", + "parameters" : [ + { + "name" : "value", + "type" : { + "jsObject" : { + + } + } + }, + { + "name" : "transform", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTests8JSObjectC_8JSObjectC", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "jsObject" : { + + } + } + ], + "returnType" : { + "jsObject" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "jsObject" : { + + } + } + }, + { + "name" : "jsMakeIntToInt", + "parameters" : [ + { + "name" : "base", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSi_Si", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "int" : { + + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "name" : "jsMakeDoubleToDouble", + "parameters" : [ + { + "name" : "base", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSd_Sd", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "double" : { + + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "name" : "jsMakeStringToString", + "parameters" : [ + { + "name" : "prefix", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSS_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + "useJSTypedClosure" : false + } + } + }, + { + "name" : "jsCallTwice", + "parameters" : [ + { + "name" : "value", + "type" : { + "int" : { + + } + } + }, + { + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSi_y", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "int" : { + + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "name" : "jsCallBinary", + "parameters" : [ + { + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSiSi_Si", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "int" : { + + } + }, + { + "int" : { + + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "name" : "jsCallTriple", + "parameters" : [ + { + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSiSiSi_Si", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "int" : { + + } + }, + { + "int" : { + + } + }, + { + "int" : { + + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "name" : "jsCallAfterRelease", + "parameters" : [ + { + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsy_y", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "name" : "jsOptionalInvoke", + "parameters" : [ + { + "name" : "callback", + "type" : { + "nullable" : { + "_0" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsy_Sb", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + + ], + "returnType" : { + "bool" : { + + } + } + }, + "useJSTypedClosure" : true + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "name" : "jsStoreClosure", + "parameters" : [ + { + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsy_y", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "jsCallStoredClosure", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "jsHeapCount", + "parameters" : [ + + ], + "returnType" : { + "int" : { + + } + } + }, + { + "name" : "runJsClosureSupportTests", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + } + ] + } + ] + }, + { + "functions" : [ + { + "name" : "jsRoundTripDictionary", + "parameters" : [ + { + "name" : "values", + "type" : { + "dictionary" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "name" : "jsRoundTripDictionaryBool", + "parameters" : [ + { + "name" : "values", + "type" : { + "dictionary" : { + "_0" : { + "bool" : { + + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "bool" : { + + } + } + } + } + }, + { + "name" : "jsRoundTripDictionaryDouble", + "parameters" : [ + { + "name" : "values", + "type" : { + "dictionary" : { + "_0" : { + "double" : { + + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "double" : { + + } + } + } + } + }, + { + "name" : "jsRoundTripDictionaryJSObject", + "parameters" : [ + { + "name" : "values", + "type" : { + "dictionary" : { + "_0" : { + "jsObject" : { + + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "jsObject" : { + + } + } + } + } + }, + { + "name" : "jsRoundTripDictionaryJSValue", + "parameters" : [ + { + "name" : "values", + "type" : { + "dictionary" : { + "_0" : { + "jsValue" : { + + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "jsValue" : { + + } + } + } + } + }, + { + "name" : "jsRoundTripNestedDictionary", + "parameters" : [ + { + "name" : "values", + "type" : { + "dictionary" : { + "_0" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + } + } + }, + { + "name" : "jsRoundTripOptionalDictionary", + "parameters" : [ + { + "name" : "values", + "type" : { + "nullable" : { + "_0" : { + "dictionary" : { + "_0" : { + "string" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "dictionary" : { + "_0" : { + "string" : { + + } + } + } + }, + "_1" : "null" + } + } + }, + { + "name" : "jsRoundTripUndefinedDictionary", + "parameters" : [ + { + "name" : "values", + "type" : { + "nullable" : { + "_0" : { + "dictionary" : { + "_0" : { + "int" : { + + } + } + } + }, + "_1" : "undefined" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "dictionary" : { + "_0" : { + "int" : { + + } + } + } + }, + "_1" : "undefined" + } + } + } + ], + "types" : [ + + ] + }, + { + "functions" : [ + + ], + "types" : [ + { + "constructor" : { + "parameters" : [ + { + "name" : "value", + "type" : { + "string" : { + + } + } + } + ] + }, + "getters" : [ + { + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "methods" : [ + + ], + "name" : "Foo", + "setters" : [ + + ], + "staticMethods" : [ + + ] + } + ] + }, + { + "functions" : [ + { + "name" : "jsRoundTripVoid", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "jsRoundTripNumber", + "parameters" : [ + { + "name" : "v", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + { + "name" : "jsRoundTripBool", + "parameters" : [ + { + "name" : "v", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "name" : "jsRoundTripString", + "parameters" : [ + { + "name" : "v", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "name" : "jsRoundTripJSValue", + "parameters" : [ + { + "name" : "v", + "type" : { + "jsValue" : { + + } + } + } + ], + "returnType" : { + "jsValue" : { + + } + } + }, + { + "name" : "jsRoundTripJSValueArray", + "parameters" : [ + { + "name" : "v", + "type" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + } + }, + { + "name" : "jsRoundTripOptionalJSValueArray", + "parameters" : [ + { + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + }, + "_1" : "null" + } + } + }, + { + "name" : "jsThrowOrVoid", + "parameters" : [ + { + "name" : "shouldThrow", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "jsThrowOrNumber", + "parameters" : [ + { + "name" : "shouldThrow", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + { + "name" : "jsThrowOrBool", + "parameters" : [ + { + "name" : "shouldThrow", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "name" : "jsThrowOrString", + "parameters" : [ + { + "name" : "shouldThrow", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "name" : "jsRoundTripFeatureFlag", + "parameters" : [ + { + "name" : "flag", + "type" : { + "rawValueEnum" : { + "_0" : "FeatureFlag", + "_1" : "String" + } + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "FeatureFlag", + "_1" : "String" + } + } + }, + { + "name" : "runAsyncWorks", + "parameters" : [ + + ], + "returnType" : { + "jsObject" : { + "_0" : "JSPromise" + } + } + }, + { + "jsName" : "$jsWeirdFunction", + "name" : "_jsWeirdFunction", + "parameters" : [ + + ], + "returnType" : { + "double" : { + + } + } + }, + { + "name" : "jsRoundTripNumberArray", + "parameters" : [ + { + "name" : "values", + "type" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + }, + { + "name" : "jsRoundTripStringArray", + "parameters" : [ + { + "name" : "values", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "name" : "jsRoundTripBoolArray", + "parameters" : [ + { + "name" : "values", + "type" : { + "array" : { + "_0" : { + "bool" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "bool" : { + + } + } + } + } + }, + { + "name" : "jsSumNumberArray", + "parameters" : [ + { + "name" : "values", + "type" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + { + "name" : "jsCreateNumberArray", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "double" : { + + } + } + } + } + }, + { + "from" : "global", + "name" : "parseInt", + "parameters" : [ + { + "name" : "string", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "double" : { + + } + } + } + ], + "globalGetters" : [ + { + "from" : "global", + "name" : "globalObject1", + "type" : { + "jsValue" : { + + } + } + } + ], + "types" : [ + { + "constructor" : { + "parameters" : [ + { + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "name" : "prefix", + "type" : { + "string" : { + + } + } + } + ] + }, + "getters" : [ + { + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "name" : "prefix", + "type" : { + "string" : { + + } + } + } + ], + "methods" : [ + { + "name" : "greet", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "name" : "changeName", + "parameters" : [ + { + "name" : "name", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "JsGreeter", + "setters" : [ + { + "functionName" : "name_set", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ], + "staticMethods" : [ + + ] + }, + { + "constructor" : { + "parameters" : [ + + ] + }, + "getters" : [ + + ], + "jsName" : "$WeirdClass", + "methods" : [ + { + "jsName" : "method-with-dashes", + "name" : "method_with_dashes", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "_WeirdClass", + "setters" : [ + + ], + "staticMethods" : [ + + ] + }, + { + "constructor" : { + "parameters" : [ + { + "name" : "value", + "type" : { + "double" : { + + } + } + } + ] + }, + "getters" : [ + + ], + "methods" : [ + { + "name" : "value", + "parameters" : [ + + ], + "returnType" : { + "double" : { + + } + } + } + ], + "name" : "StaticBox", + "setters" : [ + + ], + "staticMethods" : [ + { + "name" : "create", + "parameters" : [ + { + "name" : "value", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "jsObject" : { + "_0" : "StaticBox" + } + } + }, + { + "name" : "value", + "parameters" : [ + + ], + "returnType" : { + "double" : { + + } + } + }, + { + "name" : "makeDefault", + "parameters" : [ + + ], + "returnType" : { + "jsObject" : { + "_0" : "StaticBox" + } + } + }, + { + "jsName" : "with-dashes", + "name" : "with_dashes", + "parameters" : [ + + ], + "returnType" : { + "jsObject" : { + "_0" : "StaticBox" + } + } + } + ] + }, + { + "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" : { + + } + } + } + ], + "staticMethods" : [ + + ] + } + ] + }, + { + "functions" : [ + { + "name" : "jsRoundTripIntArray", + "parameters" : [ + { + "name" : "items", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "name" : "jsArrayLength", + "parameters" : [ + { + "name" : "items", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "name" : "makeArrayHost", + "parameters" : [ + { + "name" : "numbers", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "name" : "labels", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "jsObject" : { + "_0" : "ArrayHost" + } + } + } + ], + "types" : [ + { + "constructor" : { + "parameters" : [ + { + "name" : "numbers", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "name" : "labels", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ] + }, + "getters" : [ + { + "name" : "numbers", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "name" : "labels", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "methods" : [ + { + "name" : "concatNumbers", + "parameters" : [ + { + "name" : "values", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "name" : "concatLabels", + "parameters" : [ + { + "name" : "values", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "name" : "firstLabel", + "parameters" : [ + { + "name" : "values", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "ArrayHost", + "setters" : [ + { + "functionName" : "numbers_set", + "name" : "numbers", + "type" : { + "array" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "functionName" : "labels_set", + "name" : "labels", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "staticMethods" : [ + + ] + } + ] + }, + { + "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" : [ + { + "constructor" : { + "parameters" : [ + + ] + }, + "from" : "global", + "getters" : [ + + ], + "methods" : [ + + ], + "name" : "MyJSClassInternal", + "setters" : [ + + ], + "staticMethods" : [ + + ] + }, + { + "constructor" : { + "parameters" : [ + + ] + }, + "from" : "global", + "getters" : [ + + ], + "methods" : [ + + ], + "name" : "MyJSClassPublic", + "setters" : [ + + ], + "staticMethods" : [ + + ] + }, + { + "constructor" : { + "parameters" : [ + + ] + }, + "from" : "global", + "getters" : [ + + ], + "methods" : [ + + ], + "name" : "MyJSClassPackage", + "setters" : [ + + ], + "staticMethods" : [ + + ] + } + ] + }, + { + "functions" : [ + { + "name" : "jsFunctionWithPackageAccess", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "jsFunctionWithPublicAccess", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "jsFunctionWithInternalAccess", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "jsFunctionWithFilePrivateAccess", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "name" : "jsFunctionWithPrivateAccess", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + } + ], + "types" : [ + + ] + }, + { + "functions" : [ + + ], + "types" : [ + { + "getters" : [ + + ], + "methods" : [ + + ], + "name" : "OptionalSupportImports", + "setters" : [ + + ], + "staticMethods" : [ + { + "name" : "jsRoundTripOptionalNumberNull", + "parameters" : [ + { + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "null" + } + } + }, + { + "name" : "jsRoundTripOptionalNumberUndefined", + "parameters" : [ + { + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "undefined" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "int" : { + + } + }, + "_1" : "undefined" + } + } + }, + { + "name" : "jsRoundTripOptionalStringNull", + "parameters" : [ + { + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "name" : "jsRoundTripOptionalStringUndefined", + "parameters" : [ + { + "name" : "name", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "undefined" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "undefined" + } + } + }, + { + "name" : "runJsOptionalSupportTests", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + } + ] + } + ] + }, + { + "functions" : [ + { + "from" : "global", + "name" : "gc", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + } + ], + "types" : [ + { + "getters" : [ + + ], + "methods" : [ + + ], + "name" : "SwiftClassSupportImports", + "setters" : [ + + ], + "staticMethods" : [ + { + "name" : "jsRoundTripGreeter", + "parameters" : [ + { + "name" : "greeter", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "name" : "jsRoundTripOptionalGreeter", + "parameters" : [ + { + "name" : "greeter", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ] + } + ] + } + ] + }, + "moduleName" : "BridgeJSRuntimeTests" +} \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/GlobalThisImportTests.swift b/Tests/BridgeJSRuntimeTests/GlobalThisImportTests.swift new file mode 100644 index 000000000..fdd22401d --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/GlobalThisImportTests.swift @@ -0,0 +1,23 @@ +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 { + guard let object = try globalObject1.object else { + XCTFail("globalObject1 was not an object") + return + } + let value = object[dynamicMember: "prop_2"].number + XCTAssertEqual(value, 2) + } +} diff --git a/Tests/BridgeJSRuntimeTests/ImportAPITests.swift b/Tests/BridgeJSRuntimeTests/ImportAPITests.swift index f0112ed1a..fa97c3197 100644 --- a/Tests/BridgeJSRuntimeTests/ImportAPITests.swift +++ b/Tests/BridgeJSRuntimeTests/ImportAPITests.swift @@ -35,6 +35,56 @@ class ImportAPITests: XCTestCase { } } + func testRoundTripJSValue() throws { + let symbol = JSSymbol("roundTrip") + let bigInt = JSBigInt(_slowBridge: Int64(123456789)) + let values: [JSValue] = [ + .boolean(true), + .number(42), + .string(JSString("hello")), + .object(JSObject.global), + .null, + .undefined, + .symbol(symbol), + .bigInt(bigInt), + ] + for value in values { + try XCTAssertEqual(jsRoundTripJSValue(value), value) + } + } + + func testRoundTripJSValueArray() throws { + let object = JSObject.global + let symbol = JSSymbol("array") + let bigInt = JSBigInt(_slowBridge: Int64(42)) + let values: [JSValue] = [ + .boolean(false), + .number(123.5), + .string(JSString("hello")), + .object(object), + .null, + .undefined, + .symbol(symbol), + .bigInt(bigInt), + ] + let roundTripped = try jsRoundTripJSValueArray(values) + XCTAssertEqual(roundTripped, values) + XCTAssertEqual(try jsRoundTripJSValueArray([]), []) + } + + func testRoundTripOptionalJSValueArray() throws { + XCTAssertNil(try jsRoundTripOptionalJSValueArray(nil)) + let values: [JSValue] = [.number(1), .undefined, .null] + let result = try jsRoundTripOptionalJSValueArray(values) + XCTAssertEqual(result, values) + } + + func testRoundTripFeatureFlag() throws { + for v in [FeatureFlag.foo, .bar] { + try XCTAssertEqual(jsRoundTripFeatureFlag(v), v) + } + } + func ensureThrows(_ f: (Bool) throws(JSException) -> T) throws { do { _ = try f(true) @@ -84,4 +134,85 @@ class ImportAPITests: XCTestCase { XCTAssertEqual(try greeter.prefix, "Hello") } + + func testRoundTripIntArray() throws { + let values = [1, 2, 3, 4, 5] + let result = try jsRoundTripIntArray(values) + XCTAssertEqual(result, values) + XCTAssertEqual(try jsArrayLength(values), values.count) + XCTAssertEqual(try jsRoundTripIntArray([]), []) + } + + func testJSClassArrayMembers() throws { + let numbers = [1, 2, 3] + let labels = ["alpha", "beta"] + let host = try makeArrayHost(numbers, labels) + + XCTAssertEqual(try host.numbers, numbers) + XCTAssertEqual(try host.labels, labels) + + try host.setNumbers([10, 20]) + try host.setLabels(["gamma"]) + XCTAssertEqual(try host.numbers, [10, 20]) + XCTAssertEqual(try host.labels, ["gamma"]) + + XCTAssertEqual(try host.concatNumbers([30, 40]), [10, 20, 30, 40]) + XCTAssertEqual(try host.concatLabels(["delta", "epsilon"]), ["gamma", "delta", "epsilon"]) + XCTAssertEqual(try host.firstLabel([]), "gamma") + XCTAssertEqual(try host.firstLabel(["zeta"]), "zeta") + } + + func testJSNameFunctionAndClass() throws { + XCTAssertEqual(try _jsWeirdFunction(), 42) + + let obj = try _WeirdClass() + XCTAssertEqual(try obj.method_with_dashes(), "ok") + } + + func testJSClassStaticFunctions() throws { + let created = try StaticBox.create(10) + XCTAssertEqual(try created.value(), 10) + + let defaultBox = try StaticBox.makeDefault() + XCTAssertEqual(try defaultBox.value(), 0) + + XCTAssertEqual(try StaticBox.value(), 99) + + let dashed = try StaticBox.with_dashes() + XCTAssertEqual(try dashed.value(), 7) + } + + func testRoundTripNumberArray() throws { + let input: [Double] = [1.0, 2.5, 3.0, -4.5] + let result = try jsRoundTripNumberArray(input) + XCTAssertEqual(result, input) + XCTAssertEqual(try jsRoundTripNumberArray([]), []) + XCTAssertEqual(try jsRoundTripNumberArray([42.0]), [42.0]) + } + + func testRoundTripStringArray() throws { + let input = ["Hello", "World", "🎉"] + let result = try jsRoundTripStringArray(input) + XCTAssertEqual(result, input) + XCTAssertEqual(try jsRoundTripStringArray([]), []) + XCTAssertEqual(try jsRoundTripStringArray(["", "a", ""]), ["", "a", ""]) + } + + func testRoundTripBoolArray() throws { + let input = [true, false, true, false] + let result = try jsRoundTripBoolArray(input) + XCTAssertEqual(result, input) + XCTAssertEqual(try jsRoundTripBoolArray([]), []) + } + + func testSumNumberArray() throws { + XCTAssertEqual(try jsSumNumberArray([1.0, 2.0, 3.0, 4.0]), 10.0) + XCTAssertEqual(try jsSumNumberArray([]), 0.0) + XCTAssertEqual(try jsSumNumberArray([42.0]), 42.0) + } + + func testCreateNumberArray() throws { + let result = try jsCreateNumberArray() + XCTAssertEqual(result, [1.0, 2.0, 3.0, 4.0, 5.0]) + } } diff --git a/Tests/BridgeJSRuntimeTests/ImportArrayAPIs.swift b/Tests/BridgeJSRuntimeTests/ImportArrayAPIs.swift new file mode 100644 index 000000000..104304d5b --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/ImportArrayAPIs.swift @@ -0,0 +1,17 @@ +@_spi(BridgeJS) import JavaScriptKit + +@JSFunction func jsRoundTripIntArray(_ items: [Int]) throws(JSException) -> [Int] +@JSFunction func jsArrayLength(_ items: [Int]) throws(JSException) -> Int + +@JSClass struct ArrayHost { + @JSGetter var numbers: [Int] + @JSGetter var labels: [String] + @JSSetter func setNumbers(_ value: [Int]) throws(JSException) + @JSSetter func setLabels(_ value: [String]) throws(JSException) + @JSFunction init(_ numbers: [Int], _ labels: [String]) throws(JSException) + @JSFunction func concatNumbers(_ values: [Int]) throws(JSException) -> [Int] + @JSFunction func concatLabels(_ values: [String]) throws(JSException) -> [String] + @JSFunction func firstLabel(_ values: [String]) throws(JSException) -> String +} + +@JSFunction func makeArrayHost(_ numbers: [Int], _ labels: [String]) throws(JSException) -> ArrayHost diff --git a/Tests/BridgeJSRuntimeTests/ImportStructAPIs.swift b/Tests/BridgeJSRuntimeTests/ImportStructAPIs.swift new file mode 100644 index 000000000..41929772e --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/ImportStructAPIs.swift @@ -0,0 +1,9 @@ +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/JavaScript/ClosureSupportTests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/ClosureSupportTests.mjs new file mode 100644 index 000000000..0d5560fae --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/JavaScript/ClosureSupportTests.mjs @@ -0,0 +1,311 @@ +/** + * @returns {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Imports["ClosureSupportImports"]} + */ +export function getImports(importsContext) { + return { + jsApplyVoid: (fn) => { + fn(); + }, + jsApplyBool: (fn) => { + return fn(); + }, + jsApplyInt: (v, fn) => { + return fn(v); + }, + jsApplyDouble: (v, fn) => { + return fn(v); + }, + jsApplyString: (v, fn) => { + return fn(v); + }, + jsApplyJSValue: (v, fn) => { + return fn(v); + }, + jsApplyJSObject: (v, fn) => { + return fn(v); + }, + jsApplyArrayInt: (v, fn) => { + return fn(v); + }, + jsApplyArrayDouble: (v, fn) => { + return fn(v); + }, + jsApplyArrayString: (v, fn) => { + return fn(v); + }, + jsApplyArrayJSValue: (v, fn) => { + return fn(v); + }, + jsApplyArrayJSObject: (v, fn) => { + return fn(v); + }, + jsMakeIntToInt: (base) => { + return (v) => base + v; + }, + jsMakeDoubleToDouble: (base) => { + return (v) => base + v; + }, + jsMakeStringToString: (prefix) => { + return (name) => `${prefix}${name}`; + }, + jsCallTwice: (v, fn) => { + fn(v); + fn(v); + return v; + }, + jsCallBinary: (fn) => fn(1, 2), + jsCallTriple: (fn) => fn(1, 2, 3), + jsCallTripleMut: (fn) => { + fn(1, 2, 3); + fn(4, 5, 6); + }, + jsCallTwiceMut: (fn) => { + fn(); + fn(); + }, + jsHeapCount: () => { + globalThis.gc?.(); + return globalThis.swift?.memory?._heapValueById?.size ?? -1; + }, + jsCallAfterRelease: (fn) => { + try { + fn(); + fn(); + return "null"; + } catch (e) { + return e?.message ?? "error"; + } + }, + jsOptionalInvoke: (fn) => { + if (fn == null) { return false; } + return fn(); + }, + jsStoreClosure: (fn) => { globalThis.__storedClosure = fn; }, + jsCallStoredClosure: () => { return globalThis.__storedClosure?.(); }, + + runJsClosureSupportTests: () => { + const exports = importsContext.getExports(); + if (!exports) { throw new Error("No exports!?"); } + runJsClosureSupportTests(exports); + }, + }; +} + +import assert from "node:assert"; + +/** @param {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */ +export function runJsClosureSupportTests(exports) { + const upperTransform = (text) => text.toUpperCase(); + const processor = new exports.TextProcessor(upperTransform); + + assert.equal(processor.process("hello"), "HELLO"); + + const multiParamTransform = (count, text, ratio) => { + return `${text.toUpperCase()}-${count}-${ratio.toFixed(2)}`; + }; + assert.equal(processor.processWithCustom("world", multiParamTransform), "WORLD-42-3.14"); + assert.equal(processor.process("test"), "TEST"); + + const greeterForClosure = new exports.Greeter("World"); + const greeterCaller = new exports.Greeter("Caller"); + const customGreeting = (greeter) => `Custom greeting for ${greeter.name}: ${greeter.greet()}`; + const greetResult = greeterCaller.greetWith(greeterForClosure, customGreeting); + assert.equal(greetResult, "Custom greeting for World: Hello, World!"); + greeterForClosure.release(); + greeterCaller.release(); + + assert.equal(exports.formatName("ada", (name) => name.toUpperCase()), "ADA"); + assert.equal(exports.formatName("grace", (name) => `Dr. ${name}`), "Dr. grace"); + + const addDr = exports.makeFormatter("Dr."); + assert.equal(addDr("Ada"), "Dr. Ada"); + assert.equal(addDr("Grace"), "Dr. Grace"); + + const addProf = exports.makeFormatter("Prof."); + assert.equal(addProf("Hopper"), "Prof. Hopper"); + + const add10 = exports.makeAdder(10); + assert.equal(add10(5), 15); + assert.equal(add10(32), 42); + + const add100 = exports.makeAdder(100); + assert.equal(add100(23), 123); + + const storedTransform = processor.getTransform(); + assert.equal(storedTransform("hello"), "HELLO"); + assert.equal(storedTransform("world"), "WORLD"); + + const greeterForFormatter = new exports.Greeter("Formatter"); + const greeterFormatter = greeterForFormatter.makeFormatter(" [suffix]"); + assert.equal(greeterFormatter("test"), "Hello, Formatter! - test - [suffix]"); + assert.equal(greeterFormatter("data"), "Hello, Formatter! - data - [suffix]"); + greeterForFormatter.release(); + + const greeterCreator = exports.Greeter.makeCreator("Default"); + const createdG1 = greeterCreator("Alice"); + assert.equal(createdG1.name, "Alice"); + assert.equal(createdG1.greet(), "Hello, Alice!"); + const createdG2 = greeterCreator(""); + assert.equal(createdG2.name, "Default"); + assert.equal(createdG2.greet(), "Hello, Default!"); + createdG1.release(); + createdG2.release(); + + const greeterHost = new exports.Greeter("Host"); + const greeterGreeter = greeterHost.makeCustomGreeter(); + const guest1 = new exports.Greeter("Guest1"); + const guest2 = new exports.Greeter("Guest2"); + assert.equal(greeterGreeter(guest1), "Host greets Guest1: Hello, Guest1!"); + assert.equal(greeterGreeter(guest2), "Host greets Guest2: Hello, Guest2!"); + greeterHost.release(); + guest1.release(); + guest2.release(); + + const greeterForMethod = new exports.Greeter("Method"); + const greeterParam = new exports.Greeter("Param"); + const methodResult = greeterForMethod.greetWith(greeterParam, (g) => { + return `Custom: ${g.name} says ${g.greet()}`; + }); + assert.equal(methodResult, "Custom: Param says Hello, Param!"); + greeterForMethod.release(); + greeterParam.release(); + + const optResult1 = processor.processOptionalString((value) => { + return value !== null ? `Got: ${value}` : `Got: null`; + }); + assert.equal(optResult1, "Got: test | Got: null"); + + const optResult2 = processor.processOptionalInt((value) => { + return value !== null ? `Number: ${value}` : `Number: null`; + }); + assert.equal(optResult2, "Number: 42 | Number: null"); + + const optResult3 = processor.processOptionalGreeter((greeter) => { + return greeter !== null ? `Greeter: ${greeter.name}` : `Greeter: null`; + }); + assert.equal(optResult3, "Greeter: Alice | Greeter: null"); + + const optFormatter = processor.makeOptionalStringFormatter(); + assert.equal(optFormatter("world"), "Got: world"); + assert.equal(optFormatter(null), "Got: nil"); + + const optCreator = processor.makeOptionalGreeterCreator(); + const opt1 = optCreator(); + assert.equal(opt1, null); + const opt2 = optCreator(); + assert.notEqual(opt2, null); + assert.equal(opt2.name, "Greeter2"); + assert.equal(opt2.greet(), "Hello, Greeter2!"); + opt2.release(); + const opt3 = optCreator(); + assert.equal(opt3, null); + const opt4 = optCreator(); + assert.notEqual(opt4, null); + assert.equal(opt4.name, "Greeter4"); + opt4.release(); + + const dirResult = processor.processDirection((dir) => { + switch (dir) { + case exports.Direction.North: return "Going North"; + case exports.Direction.South: return "Going South"; + case exports.Direction.East: return "Going East"; + case exports.Direction.West: return "Going West"; + default: return "Unknown"; + } + }); + assert.equal(dirResult, "Going North"); + + const themeResult = processor.processTheme((theme) => { + return theme === exports.Theme.Dark ? "Dark mode" : "Light mode"; + }); + assert.equal(themeResult, "Dark mode"); + + const statusResult = processor.processHttpStatus((status) => { + return status; + }); + assert.equal(statusResult, exports.HttpStatus.Ok); + + const apiResult = processor.processAPIResult((result) => { + if (result.tag === exports.APIResult.Tag.Success) { + return `API Success: ${result.param0}`; + } + return "API Other"; + }); + assert.equal(apiResult, "API Success: test"); + + const dirChecker = processor.makeDirectionChecker(); + assert.equal(dirChecker(exports.Direction.North), true); + assert.equal(dirChecker(exports.Direction.South), true); + assert.equal(dirChecker(exports.Direction.East), false); + assert.equal(dirChecker(exports.Direction.West), false); + + const themeValidator = processor.makeThemeValidator(); + assert.equal(themeValidator(exports.Theme.Dark), true); + assert.equal(themeValidator(exports.Theme.Light), false); + assert.equal(themeValidator(exports.Theme.Auto), false); + + const statusExtractor = processor.makeStatusCodeExtractor(); + assert.equal(statusExtractor(exports.HttpStatus.Ok), 200); + assert.equal(statusExtractor(exports.HttpStatus.NotFound), 404); + assert.equal(statusExtractor(exports.HttpStatus.ServerError), 500); + assert.equal(statusExtractor(exports.HttpStatus.Unknown), -1); + + const apiHandler = processor.makeAPIResultHandler(); + assert.equal(apiHandler({ tag: exports.APIResult.Tag.Success, param0: "done" }), "Success: done"); + assert.equal(apiHandler({ tag: exports.APIResult.Tag.Failure, param0: 500 }), "Failure: 500"); + assert.equal(apiHandler({ tag: exports.APIResult.Tag.Info }), "Info"); + assert.equal(apiHandler({ tag: exports.APIResult.Tag.Flag, param0: true }), "Flag: true"); + assert.equal(apiHandler({ tag: exports.APIResult.Tag.Rate, param0: 1.5 }), "Rate: 1.5"); + assert.equal(apiHandler({ tag: exports.APIResult.Tag.Precise, param0: 3.14159 }), "Precise: 3.14159"); + + const optDirResult = processor.processOptionalDirection((dir) => { + return dir !== null ? `Dir: ${dir}` : "Dir: null"; + }); + assert.equal(optDirResult, `Dir: ${exports.Direction.North} | Dir: null`); + + const optThemeResult = processor.processOptionalTheme((theme) => { + return theme !== null ? `Theme: ${theme}` : "Theme: null"; + }); + assert.equal(optThemeResult, `Theme: ${exports.Theme.Light} | Theme: null`); + + const optApiResult = processor.processOptionalAPIResult((result) => { + if (result === null) return "Result: null"; + if (result.tag === exports.APIResult.Tag.Success) { + return `Result: Success(${result.param0})`; + } + return "Result: other"; + }); + assert.equal(optApiResult, "Result: Success(ok) | Result: null"); + + const optDirFormatter = processor.makeOptionalDirectionFormatter(); + assert.equal(optDirFormatter(exports.Direction.North), "N"); + assert.equal(optDirFormatter(exports.Direction.South), "S"); + assert.equal(optDirFormatter(exports.Direction.East), "E"); + assert.equal(optDirFormatter(exports.Direction.West), "W"); + assert.equal(optDirFormatter(null), "nil"); + + processor.release(); + + + const intToInt = exports.ClosureSupportExports.makeIntToInt(10); + assert.equal(intToInt(0), 10); + assert.equal(intToInt(32), 42); + + const doubleToDouble = exports.ClosureSupportExports.makeDoubleToDouble(10.0); + assert.equal(doubleToDouble(0.0), 10.0); + assert.equal(doubleToDouble(32.0), 42.0); + + const stringToString = exports.ClosureSupportExports.makeStringToString("Hello, "); + assert.equal(stringToString("world!"), "Hello, world!"); + + const jsIntToInt = exports.ClosureSupportExports.makeJSIntToInt(10); + assert.equal(jsIntToInt(0), 10); + assert.equal(jsIntToInt(32), 42); + + const jsDoubleToDouble = exports.ClosureSupportExports.makeJSDoubleToDouble(10.0); + assert.equal(jsDoubleToDouble(0.0), 10.0); + assert.equal(jsDoubleToDouble(32.0), 42.0); + + const jsStringToString = exports.ClosureSupportExports.makeJSStringToString("Hello, "); + assert.equal(jsStringToString("world!"), "Hello, world!"); +} diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs new file mode 100644 index 000000000..58215560c --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs @@ -0,0 +1,246 @@ +// @ts-check + +import assert from 'node:assert'; +import { + StatusValues, + ThemeValues, + HttpStatusValues, + TSDirection, + TSTheme, + APIResultValues, + APIOptionalResultValues, + AllTypesResultValues, + OptionalAllTypesResultValues, +} from '../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.js'; + +import { ImportedFoo } from './Types.mjs'; + +/** + * @returns {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Imports["OptionalSupportImports"]} + */ +export function getImports(importsContext) { + return { + jsRoundTripOptionalNumberNull: (v) => { + return v ?? null; + }, + jsRoundTripOptionalNumberUndefined: (v) => { + return v === undefined ? undefined : v; + }, + jsRoundTripOptionalStringNull: (v) => { + return v ?? null; + }, + jsRoundTripOptionalStringUndefined: (v) => { + return v === undefined ? undefined : v; + }, + runJsOptionalSupportTests: () => { + const exports = importsContext.getExports(); + if (!exports) { throw new Error("No exports!?"); } + runJsOptionalSupportTests(exports); + }, + }; +} + +/** + * Optional value bridging coverage for BridgeJS runtime tests. + * @param {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports + */ +export function runJsOptionalSupportTests(exports) { + assert.equal(exports.roundTripOptionalString(null), null); + assert.equal(exports.roundTripOptionalInt(null), null); + assert.equal(exports.roundTripOptionalBool(null), null); + assert.equal(exports.roundTripOptionalFloat(null), null); + assert.equal(exports.roundTripOptionalDouble(null), null); + + assert.equal(exports.roundTripOptionalString('Hello'), 'Hello'); + assert.equal(exports.roundTripOptionalInt(42), 42); + assert.equal(exports.roundTripOptionalBool(true), true); + assert.equal(exports.roundTripOptionalFloat(3.141592502593994), 3.141592502593994); // Float32 precision + assert.equal(exports.roundTripOptionalDouble(2.718), 2.718); + + assert.equal(exports.roundTripOptionalSyntax(null), null); + assert.equal(exports.roundTripOptionalSyntax('Test'), 'Test'); + assert.equal(exports.roundTripOptionalMixSyntax(null), null); + assert.equal(exports.roundTripOptionalMixSyntax('Mix'), 'Mix'); + assert.equal(exports.roundTripOptionalSwiftSyntax(null), null); + assert.equal(exports.roundTripOptionalSwiftSyntax('Swift'), 'Swift'); + assert.equal(exports.roundTripOptionalWithSpaces(null), null); + assert.equal(exports.roundTripOptionalWithSpaces(1.618), 1.618); + assert.equal(exports.roundTripOptionalTypeAlias(null), null); + assert.equal(exports.roundTripOptionalTypeAlias(25), 25); + assert.equal(exports.roundTripOptionalStatus(exports.Status.Success), StatusValues.Success); + assert.equal(exports.roundTripOptionalTheme(exports.Theme.Light), ThemeValues.Light); + assert.equal(exports.roundTripOptionalHttpStatus(exports.HttpStatus.Ok), HttpStatusValues.Ok); + assert.equal(exports.roundTripOptionalTSDirection(TSDirection.North), TSDirection.North); + assert.equal(exports.roundTripOptionalTSTheme(TSTheme.Light), TSTheme.Light); + assert.equal(exports.roundTripOptionalNetworkingAPIMethod(exports.Networking.API.Method.Get), exports.Networking.API.Method.Get); + + const pVal = 3.141592653589793; + const p1 = { tag: APIResultValues.Tag.Precise, param0: pVal }; + const cl1 = { tag: exports.ComplexResult.Tag.Location, param0: 37.7749, param1: -122.4194, param2: 'San Francisco' }; + + assert.deepEqual(exports.roundTripOptionalAPIResult(p1), p1); + assert.deepEqual(exports.roundTripOptionalComplexResult(cl1), cl1); + + const apiSuccess = { tag: exports.APIResult.Tag.Success, param0: 'test success' }; + const apiFailure = { tag: exports.APIResult.Tag.Failure, param0: 404 }; + const apiInfo = { tag: exports.APIResult.Tag.Info }; + + assert.equal(exports.compareAPIResults(apiSuccess, apiFailure), 'r1:success:test success,r2:failure:404'); + assert.equal(exports.compareAPIResults(null, apiInfo), 'r1:nil,r2:info'); + assert.equal(exports.compareAPIResults(apiFailure, null), 'r1:failure:404,r2:nil'); + assert.equal(exports.compareAPIResults(null, null), 'r1:nil,r2:nil'); + + const optionalGreeter = new exports.Greeter('Schrödinger'); + const optionalGreeter2 = exports.roundTripOptionalClass(optionalGreeter); + assert.equal(optionalGreeter2?.greet() ?? '', 'Hello, Schrödinger!'); + assert.equal(optionalGreeter2?.name ?? '', 'Schrödinger'); + assert.equal(optionalGreeter2?.prefix ?? '', 'Hello'); + assert.equal(exports.roundTripOptionalClass(null), null); + optionalGreeter.release(); + optionalGreeter2?.release(); + + const optionalsHolder = new exports.OptionalPropertyHolder(null); + + assert.equal(optionalsHolder.optionalName, null); + assert.equal(optionalsHolder.optionalAge, null); + assert.equal(optionalsHolder.optionalGreeter, null); + + optionalsHolder.optionalName = 'Alice'; + optionalsHolder.optionalAge = 25; + assert.equal(optionalsHolder.optionalName, 'Alice'); + assert.equal(optionalsHolder.optionalAge, 25); + + const testPropertyGreeter = new exports.Greeter('Bob'); + optionalsHolder.optionalGreeter = testPropertyGreeter; + assert.equal(optionalsHolder.optionalGreeter.greet(), 'Hello, Bob!'); + assert.equal(optionalsHolder.optionalGreeter.name, 'Bob'); + + optionalsHolder.optionalName = null; + optionalsHolder.optionalAge = null; + optionalsHolder.optionalGreeter = null; + assert.equal(optionalsHolder.optionalName, null); + assert.equal(optionalsHolder.optionalAge, null); + assert.equal(optionalsHolder.optionalGreeter, null); + testPropertyGreeter.release(); + optionalsHolder.release(); + + const optGreeter = new exports.Greeter('Optionaly'); + assert.equal(exports.roundTripOptionalGreeter(null), null); + const optGreeterReturned = exports.roundTripOptionalGreeter(optGreeter); + assert.equal(optGreeterReturned.name, 'Optionaly'); + assert.equal(optGreeterReturned.greet(), 'Hello, Optionaly!'); + + const appliedOptional = exports.applyOptionalGreeter(null, (g) => g ?? optGreeter); + assert.equal(appliedOptional.name, 'Optionaly'); + + const holderOpt = exports.makeOptionalHolder(null, undefined); + assert.equal(holderOpt.nullableGreeter, null); + assert.equal(holderOpt.undefinedNumber, undefined); + holderOpt.nullableGreeter = optGreeter; + holderOpt.undefinedNumber = 123.5; + assert.equal(holderOpt.nullableGreeter.name, 'Optionaly'); + assert.equal(holderOpt.undefinedNumber, 123.5); + holderOpt.release(); + optGreeterReturned.release(); + optGreeter.release(); + + const aor1 = { tag: APIOptionalResultValues.Tag.Success, param0: 'hello world' }; + const aor2 = { tag: APIOptionalResultValues.Tag.Success, param0: null }; + const aor3 = { tag: APIOptionalResultValues.Tag.Failure, param0: 404, param1: true }; + const aor4 = { tag: APIOptionalResultValues.Tag.Failure, param0: 404, param1: null }; + const aor5 = { tag: APIOptionalResultValues.Tag.Failure, param0: null, param1: null }; + const aor6 = { tag: APIOptionalResultValues.Tag.Status, param0: true, param1: 200, param2: 'OK' }; + const aor7 = { tag: APIOptionalResultValues.Tag.Status, param0: true, param1: null, param2: 'Partial' }; + const aor8 = { tag: APIOptionalResultValues.Tag.Status, param0: null, param1: null, param2: 'Zero' }; + const aor9 = { tag: APIOptionalResultValues.Tag.Status, param0: false, param1: 500, param2: null }; + const aor10 = { tag: APIOptionalResultValues.Tag.Status, param0: null, param1: 0, param2: 'Zero' }; + + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor1), aor1); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor2), aor2); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor3), aor3); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor4), aor4); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor5), aor5); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor6), aor6); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor7), aor7); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor8), aor8); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor9), aor9); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor10), aor10); + assert.equal(exports.roundTripOptionalAPIOptionalResult(null), null); + + // Optional TypedPayloadResult roundtrip + const tpr_precision = { tag: exports.TypedPayloadResult.Tag.Precision, param0: Math.fround(0.1) }; + assert.deepEqual(exports.roundTripOptionalTypedPayloadResult(tpr_precision), tpr_precision); + const tpr_direction = { tag: exports.TypedPayloadResult.Tag.Direction, param0: exports.Direction.North }; + assert.deepEqual(exports.roundTripOptionalTypedPayloadResult(tpr_direction), tpr_direction); + const tpr_optPrecisionSome = { tag: exports.TypedPayloadResult.Tag.OptPrecision, param0: Math.fround(0.001) }; + assert.deepEqual(exports.roundTripOptionalTypedPayloadResult(tpr_optPrecisionSome), tpr_optPrecisionSome); + const tpr_optPrecisionNull = { tag: exports.TypedPayloadResult.Tag.OptPrecision, param0: null }; + assert.deepEqual(exports.roundTripOptionalTypedPayloadResult(tpr_optPrecisionNull), tpr_optPrecisionNull); + const tpr_empty = { tag: exports.TypedPayloadResult.Tag.Empty }; + assert.deepEqual(exports.roundTripOptionalTypedPayloadResult(tpr_empty), tpr_empty); + assert.equal(exports.roundTripOptionalTypedPayloadResult(null), null); + + // Optional AllTypesResult roundtrip + const atr_struct = { tag: AllTypesResultValues.Tag.StructPayload, param0: { street: "100 Main St", city: "Boston", zipCode: 2101 } }; + assert.deepEqual(exports.roundTripOptionalAllTypesResult(atr_struct), atr_struct); + const atr_array = { tag: AllTypesResultValues.Tag.ArrayPayload, param0: [10, 20, 30] }; + assert.deepEqual(exports.roundTripOptionalAllTypesResult(atr_array), atr_array); + const atr_empty = { tag: AllTypesResultValues.Tag.Empty }; + assert.deepEqual(exports.roundTripOptionalAllTypesResult(atr_empty), atr_empty); + assert.equal(exports.roundTripOptionalAllTypesResult(null), null); + + // OptionalAllTypesResult — optional struct, class, JSObject, nested enum, array as associated value payloads + const oatr_structSome = { tag: OptionalAllTypesResultValues.Tag.OptStruct, param0: { street: "200 Oak St", city: "Denver", zipCode: null } }; + assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_structSome), oatr_structSome); + + const oatr_structNone = { tag: OptionalAllTypesResultValues.Tag.OptStruct, param0: null }; + assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_structNone), oatr_structNone); + + const oatr_classSome = { tag: OptionalAllTypesResultValues.Tag.OptClass, param0: new exports.Greeter("OptEnumUser") }; + const oatr_classSome_result = exports.roundTripOptionalPayloadResult(oatr_classSome); + assert.equal(oatr_classSome_result.tag, OptionalAllTypesResultValues.Tag.OptClass); + assert.equal(oatr_classSome_result.param0.name, "OptEnumUser"); + + const oatr_classNone = { tag: OptionalAllTypesResultValues.Tag.OptClass, param0: null }; + assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_classNone), oatr_classNone); + + const oatr_jsObjectSome = { tag: OptionalAllTypesResultValues.Tag.OptJSObject, param0: { key: "value" } }; + const oatr_jsObjectSome_result = exports.roundTripOptionalPayloadResult(oatr_jsObjectSome); + assert.equal(oatr_jsObjectSome_result.tag, OptionalAllTypesResultValues.Tag.OptJSObject); + assert.equal(oatr_jsObjectSome_result.param0.key, "value"); + + const oatr_jsObjectNone = { tag: OptionalAllTypesResultValues.Tag.OptJSObject, param0: null }; + assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_jsObjectNone), oatr_jsObjectNone); + + const oatr_nestedEnumSome = { tag: OptionalAllTypesResultValues.Tag.OptNestedEnum, param0: { tag: APIResultValues.Tag.Failure, param0: 404 } }; + assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_nestedEnumSome), oatr_nestedEnumSome); + + const oatr_nestedEnumNone = { tag: OptionalAllTypesResultValues.Tag.OptNestedEnum, param0: null }; + assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_nestedEnumNone), oatr_nestedEnumNone); + + const oatr_arraySome = { tag: OptionalAllTypesResultValues.Tag.OptArray, param0: [1, 2, 3] }; + assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_arraySome), oatr_arraySome); + + const oatr_arrayNone = { tag: OptionalAllTypesResultValues.Tag.OptArray, param0: null }; + assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_arrayNone), oatr_arrayNone); + + const oatr_jsClassSome = { tag: OptionalAllTypesResultValues.Tag.OptJsClass, param0: new ImportedFoo("optEnumFoo") }; + const oatr_jsClassSome_result = exports.roundTripOptionalPayloadResult(oatr_jsClassSome); + assert.equal(oatr_jsClassSome_result.tag, OptionalAllTypesResultValues.Tag.OptJsClass); + assert.equal(oatr_jsClassSome_result.param0.value, "optEnumFoo"); + + const oatr_jsClassNone = { tag: OptionalAllTypesResultValues.Tag.OptJsClass, param0: null }; + assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_jsClassNone), oatr_jsClassNone); + + const oatr_empty = { tag: OptionalAllTypesResultValues.Tag.Empty }; + assert.deepEqual(exports.roundTripOptionalPayloadResult(oatr_empty), oatr_empty); + + // Optional OptionalAllTypesResult roundtrip + assert.deepEqual(exports.roundTripOptionalPayloadResultOpt(oatr_structSome), oatr_structSome); + assert.deepEqual(exports.roundTripOptionalPayloadResultOpt(oatr_structNone), oatr_structNone); + assert.deepEqual(exports.roundTripOptionalPayloadResultOpt(oatr_empty), oatr_empty); + assert.equal(exports.roundTripOptionalPayloadResultOpt(null), null); + + exports.takeOptionalJSObject(null); + assert.doesNotThrow(() => exports.takeOptionalJSObject({ key: "value" })); +} diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs new file mode 100644 index 000000000..0368cb74a --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs @@ -0,0 +1,13 @@ +/** + * @returns {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Imports["SwiftClassSupportImports"]} + */ +export function getImports(importsContext) { + return { + jsRoundTripGreeter: (greeter) => { + return greeter; + }, + jsRoundTripOptionalGreeter: (greeter) => { + return greeter; + }, + }; +} \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/Types.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/Types.mjs new file mode 100644 index 000000000..b4c2079d8 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/JavaScript/Types.mjs @@ -0,0 +1,6 @@ +export class ImportedFoo { + /** @param {string} value */ + constructor(value) { + this.value = value; + } +} diff --git a/Tests/BridgeJSRuntimeTests/MacroCompileTests/JSClassCompileTests.swift b/Tests/BridgeJSRuntimeTests/MacroCompileTests/JSClassCompileTests.swift new file mode 100644 index 000000000..05a23d9de --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/MacroCompileTests/JSClassCompileTests.swift @@ -0,0 +1,11 @@ +import JavaScriptKit + +@JSClass(from: .global) internal struct MyJSClassInternal { + @JSFunction init() throws(JSException) +} +@JSClass(from: .global) public struct MyJSClassPublic { + @JSFunction init() throws(JSException) +} +@JSClass(from: .global) package struct MyJSClassPackage { + @JSFunction init() throws(JSException) +} diff --git a/Tests/BridgeJSRuntimeTests/MacroCompileTests/JSFunctionCompileTests.swift b/Tests/BridgeJSRuntimeTests/MacroCompileTests/JSFunctionCompileTests.swift new file mode 100644 index 000000000..e74c84d51 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/MacroCompileTests/JSFunctionCompileTests.swift @@ -0,0 +1,7 @@ +import JavaScriptKit + +@JSFunction package func jsFunctionWithPackageAccess() throws(JSException) +@JSFunction public func jsFunctionWithPublicAccess() throws(JSException) +@JSFunction internal func jsFunctionWithInternalAccess() throws(JSException) +@JSFunction fileprivate func jsFunctionWithFilePrivateAccess() throws(JSException) +@JSFunction private func jsFunctionWithPrivateAccess() throws(JSException) diff --git a/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift b/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift new file mode 100644 index 000000000..a99bb0bb1 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift @@ -0,0 +1,231 @@ +import XCTest +import JavaScriptKit +import JavaScriptEventLoop + +@JSClass struct OptionalSupportImports { + @JSFunction static func jsRoundTripOptionalNumberNull(_ value: Int?) throws -> Int? + @JSFunction static func jsRoundTripOptionalNumberUndefined(_ value: JSUndefinedOr) throws -> JSUndefinedOr + @JSFunction static func jsRoundTripOptionalStringNull(_ name: String?) throws -> String? + @JSFunction static func jsRoundTripOptionalStringUndefined( + _ name: JSUndefinedOr + ) throws -> JSUndefinedOr + + @JSFunction static func runJsOptionalSupportTests() throws(JSException) +} + +final class OptionalSupportTests: XCTestCase { + func testRunJsOptionalSupportTests() throws { + try OptionalSupportImports.runJsOptionalSupportTests() + } + + private func roundTripTest(_ fn: (T?) throws -> T?, _ some: T) throws { + try XCTAssertNil(fn(nil)) + try XCTAssertEqual(fn(some), some) + } + private func roundTripTest(_ fn: (JSUndefinedOr) throws -> JSUndefinedOr, _ some: T) throws { + let undefined = try fn(.undefined) + if case .value = undefined { + XCTFail("Expected undefined") + } + let value = try fn(.value(some)) + switch value { + case .value(let value): + XCTAssertEqual(value, some) + case .undefined: + XCTFail("Expected defined value") + } + } + + func testRoundTripOptionalStringNull() throws { + try roundTripTest(OptionalSupportImports.jsRoundTripOptionalStringNull, "hello") + } + + func testRoundTripOptionalStringUndefined() throws { + try roundTripTest(OptionalSupportImports.jsRoundTripOptionalStringUndefined, "hi") + } + + func testRoundTripOptionalNumberNull() throws { + try roundTripTest(OptionalSupportImports.jsRoundTripOptionalNumberNull, 42) + } + + func testRoundTripOptionalNumberUndefined() throws { + try roundTripTest(OptionalSupportImports.jsRoundTripOptionalNumberUndefined, 42) + } +} + +// MARK: - Optional Bridging + +@JS func roundTripOptionalString(name: String?) -> String? { + name +} + +@JS func roundTripOptionalInt(value: Int?) -> Int? { + value +} + +@JS func roundTripOptionalBool(flag: Bool?) -> Bool? { + flag +} + +@JS func roundTripOptionalFloat(number: Float?) -> Float? { + number +} + +@JS func roundTripOptionalDouble(precision: Double?) -> Double? { + precision +} + +@JS func roundTripOptionalSyntax(name: Optional) -> Optional { + name +} + +@JS func roundTripOptionalMixSyntax(name: String?) -> Optional { + name +} + +@JS func roundTripOptionalSwiftSyntax(name: Swift.Optional) -> Swift.Optional { + name +} + +@JS func roundTripOptionalWithSpaces(value: Optional) -> Optional { + value +} + +typealias OptionalAge = Int? +@JS func roundTripOptionalTypeAlias(age: OptionalAge) -> OptionalAge { + age +} + +@JS func roundTripOptionalStatus(value: Status?) -> Status? { + value +} + +@JS func roundTripOptionalTheme(value: Theme?) -> Theme? { + value +} + +@JS func roundTripOptionalHttpStatus(value: HttpStatus?) -> HttpStatus? { + value +} + +@JS func roundTripOptionalTSDirection(value: TSDirection?) -> TSDirection? { + value +} + +@JS func roundTripOptionalTSTheme(value: TSTheme?) -> TSTheme? { + value +} + +@JS func roundTripOptionalNetworkingAPIMethod(_ method: Networking.API.Method?) -> Networking.API.Method? { + method +} + +@JS func roundTripOptionalAPIResult(value: APIResult?) -> APIResult? { + value +} + +@JS func roundTripOptionalTypedPayloadResult(_ result: TypedPayloadResult?) -> TypedPayloadResult? { + result +} + +@JS func takeOptionalJSObject(_ value: JSObject?) {} + +@JS func compareAPIResults(_ r1: APIResult?, _ r2: APIResult?) -> String { + let r1Str: String + switch r1 { + case .none: r1Str = "nil" + case .some(.success(let msg)): r1Str = "success:\(msg)" + case .some(.failure(let code)): r1Str = "failure:\(code)" + case .some(.info): r1Str = "info" + case .some(.flag(let b)): r1Str = "flag:\(b)" + case .some(.rate(let r)): r1Str = "rate:\(r)" + case .some(.precise(let p)): r1Str = "precise:\(p)" + } + + let r2Str: String + switch r2 { + case .none: r2Str = "nil" + case .some(.success(let msg)): r2Str = "success:\(msg)" + case .some(.failure(let code)): r2Str = "failure:\(code)" + case .some(.info): r2Str = "info" + case .some(.flag(let b)): r2Str = "flag:\(b)" + case .some(.rate(let r)): r2Str = "rate:\(r)" + case .some(.precise(let p)): r2Str = "precise:\(p)" + } + + return "r1:\(r1Str),r2:\(r2Str)" +} + +@JS func roundTripOptionalComplexResult(_ result: ComplexResult?) -> ComplexResult? { + result +} + +@JS func roundTripOptionalAllTypesResult(_ result: AllTypesResult?) -> AllTypesResult? { + result +} + +@JS +enum OptionalAllTypesResult { + case optStruct(Address?) + case optClass(Greeter?) + case optJSObject(JSObject?) + case optNestedEnum(APIResult?) + case optArray([Int]?) + case optJsClass(Foo?) + case empty +} + +@JS func roundTripOptionalPayloadResult(_ result: OptionalAllTypesResult) -> OptionalAllTypesResult { + result +} + +@JS func roundTripOptionalPayloadResultOpt(_ result: OptionalAllTypesResult?) -> OptionalAllTypesResult? { + result +} + +@JS func roundTripOptionalClass(value: Greeter?) -> Greeter? { + value +} + +@JS func roundTripOptionalGreeter(_ value: Greeter?) -> Greeter? { + value +} + +@JS func applyOptionalGreeter(_ value: Greeter?, _ transform: (Greeter?) -> Greeter?) -> Greeter? { + transform(value) +} + +@JS class OptionalHolder { + @JS var nullableGreeter: Greeter? + @JS var undefinedNumber: JSUndefinedOr + + @JS init(nullableGreeter: Greeter?, undefinedNumber: JSUndefinedOr) { + self.nullableGreeter = nullableGreeter + self.undefinedNumber = undefinedNumber + } +} + +@JS func makeOptionalHolder(nullableGreeter: Greeter?, undefinedNumber: JSUndefinedOr) -> OptionalHolder { + OptionalHolder(nullableGreeter: nullableGreeter, undefinedNumber: undefinedNumber) +} + +@JS class OptionalPropertyHolder { + @JS var optionalName: String? + @JS var optionalAge: Int? = nil + @JS var optionalGreeter: Greeter? = nil + + @JS init(optionalName: String?) { + self.optionalName = optionalName + } +} + +@JS +enum APIOptionalResult { + case success(String?) + case failure(Int?, Bool?) + case status(Bool?, Int?, String?) +} + +@JS func roundTripOptionalAPIOptionalResult(result: APIOptionalResult?) -> APIOptionalResult? { + result +} diff --git a/Tests/BridgeJSRuntimeTests/StructAPIs.swift b/Tests/BridgeJSRuntimeTests/StructAPIs.swift new file mode 100644 index 000000000..6c0079dd1 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/StructAPIs.swift @@ -0,0 +1,275 @@ +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 public struct PublicPoint { + public var x: Int + public var y: Int + + @JS public init(x: Int, y: Int) { + self.x = x + self.y = y + } +} + +@JS struct Address { + var street: String + var city: String + 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 public func roundTripPublicPoint(_ point: PublicPoint) -> PublicPoint { + point +} + +@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) +} + +// Struct with JSObject fields +@JS struct JSObjectContainer { + var object: JSObject + var optionalObject: JSObject? +} + +@JS func roundTripJSObjectContainer(_ container: JSObjectContainer) -> JSObjectContainer { + return container +} + +// Struct with @JSClass fields (Foo is defined in ExportAPITests.swift) +@JS struct FooContainer { + var foo: Foo + var optionalFoo: Foo? +} + +@JS func roundTripFooContainer(_ container: FooContainer) -> FooContainer { + return container +} + +@JS struct ArrayMembers { + var ints: [Int] + var optStrings: [String]? + + @JS func sumValues(_ values: [Int]) -> Int { + values.reduce(0, +) + } + + @JS func firstString(_ values: [String]) -> String? { + values.first + } +} + +@JS func roundTripArrayMembers(_ value: ArrayMembers) -> ArrayMembers { + value +} + +@JS func arrayMembersSum(_ value: ArrayMembers, _ values: [Int]) -> Int { + value.sumValues(values) +} + +@JS func arrayMembersFirst(_ value: ArrayMembers, _ values: [String]) -> String? { + value.firstString(values) +} diff --git a/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift b/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift new file mode 100644 index 000000000..d9a68b1cc --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift @@ -0,0 +1,60 @@ +import XCTest +import JavaScriptKit + +@JSClass struct SwiftClassSupportImports { + @JSFunction static func jsRoundTripGreeter(_ greeter: Greeter) throws(JSException) -> Greeter + @JSFunction static func jsRoundTripOptionalGreeter(_ greeter: Greeter?) throws(JSException) -> Greeter? +} + +@JSFunction(from: .global) func gc() throws(JSException) -> Void + +final class SwiftClassSupportTests: XCTestCase { + func testRoundTripGreeter() throws { + let greeter = try SwiftClassSupportImports.jsRoundTripGreeter(Greeter(name: "Hello")) + XCTAssertEqual(greeter.name, "Hello") + } + + func testRoundTripOptionalGreeter() throws { + let greeter1 = try SwiftClassSupportImports.jsRoundTripOptionalGreeter(nil) + XCTAssertNil(greeter1) + + let greeter2 = try SwiftClassSupportImports.jsRoundTripOptionalGreeter(Greeter(name: "Hello")) + XCTAssertEqual(greeter2?.name, "Hello") + } + + func testSwiftClassToJSObject() throws { + let greeter = Greeter(name: "BridgeJS") + let jsGreeter = try XCTUnwrap(greeter.jsValue.object) + XCTAssertEqual(jsGreeter["name"].string, "BridgeJS") + } + + func testJSWrapperIsDeallocatedAfterFinalization() async throws { + weak var weakGreeter: Greeter? + var wrapperObject: JSObject? + do { + let greeter: Greeter = Greeter(name: "Hello") + weakGreeter = greeter + // Create a JS wrapper object but don't keep a reference to it + wrapperObject = try XCTUnwrap(greeter.jsValue.object) + } + // Here, the wrapper object is still alive so the greeter should still be alive + XCTAssertNotNil(weakGreeter) + + // Release the strong reference to the greeter + wrapperObject = nil + _ = wrapperObject + + // Trigger garbage collection to call the finalizer of the JS wrapper object + for _ in 0..<100 { + try gc() + // Tick the event loop to allow the garbage collector to run finalizers + // registered by FinalizationRegistry. + try await Task.sleep(for: .milliseconds(0)) + if weakGreeter == nil { + break + } + } + // Here, the greeter should be deallocated + XCTAssertNil(weakGreeter) + } +} 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.config.json b/Tests/BridgeJSRuntimeTests/bridge-js.config.json index 9e26dfeeb..55a95efaa 100644 --- a/Tests/BridgeJSRuntimeTests/bridge-js.config.json +++ b/Tests/BridgeJSRuntimeTests/bridge-js.config.json @@ -1 +1,3 @@ -{} \ No newline at end of file +{ + "exposeToGlobal": false +} \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/bridge-js.d.ts b/Tests/BridgeJSRuntimeTests/bridge-js.d.ts index 0f0d01556..ff69f5de9 100644 --- a/Tests/BridgeJSRuntimeTests/bridge-js.d.ts +++ b/Tests/BridgeJSRuntimeTests/bridge-js.d.ts @@ -2,11 +2,22 @@ export function jsRoundTripVoid(): void export function jsRoundTripNumber(v: number): number export function jsRoundTripBool(v: boolean): boolean export function jsRoundTripString(v: string): string +export type JSValue = any +export function jsRoundTripJSValue(v: JSValue): JSValue +export function jsRoundTripJSValueArray(v: JSValue[]): JSValue[] +export function jsRoundTripOptionalJSValueArray(v: JSValue[] | null): JSValue[] | null export function jsThrowOrVoid(shouldThrow: boolean): void export function jsThrowOrNumber(shouldThrow: boolean): number export function jsThrowOrBool(shouldThrow: boolean): boolean export function jsThrowOrString(shouldThrow: boolean): string +export enum FeatureFlag { + foo = "foo", + bar = "bar", +} + +export function jsRoundTripFeatureFlag(flag: FeatureFlag): FeatureFlag + export class JsGreeter { name: string; readonly prefix: string; @@ -16,3 +27,26 @@ export class JsGreeter { } export function runAsyncWorks(): Promise; + +// jsName tests +export function $jsWeirdFunction(): number; + +export class $WeirdClass { + constructor(); + "method-with-dashes"(): string; +} + +export class StaticBox { + constructor(value: number); + value(): number; + static create(value: number): StaticBox; + static value(): number; + static makeDefault(): StaticBox; + static "with-dashes"(): StaticBox; +} + +export function jsRoundTripNumberArray(values: number[]): number[]; +export function jsRoundTripStringArray(values: string[]): string[]; +export function jsRoundTripBoolArray(values: boolean[]): boolean[]; +export function jsSumNumberArray(values: number[]): number; +export function jsCreateNumberArray(): number[]; 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/JavaScriptEventLoopTests/WebWorkerDedicatedExecutorTests.swift b/Tests/JavaScriptEventLoopTests/WebWorkerDedicatedExecutorTests.swift index b6c2bd8db..aae8c2cea 100644 --- a/Tests/JavaScriptEventLoopTests/WebWorkerDedicatedExecutorTests.swift +++ b/Tests/JavaScriptEventLoopTests/WebWorkerDedicatedExecutorTests.swift @@ -2,6 +2,7 @@ import XCTest @testable import JavaScriptEventLoop +@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) final class WebWorkerDedicatedExecutorTests: XCTestCase { actor MyActor { let executor: WebWorkerDedicatedExecutor 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 ffab816ab..280a17b62 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: @@ -243,15 +243,9 @@ class JavaScriptKitTests: XCTestCase { let bigInt: JSValue = js.bi XCTAssertNotNil(JSObject.construct(from: object)) - XCTAssertEqual(JSObject.construct(from: function).map { $0 is JSFunction }, .some(true)) XCTAssertEqual(JSObject.construct(from: symbol).map { $0 is JSSymbol }, .some(true)) XCTAssertEqual(JSObject.construct(from: bigInt).map { $0 is JSBigInt }, .some(true)) - XCTAssertNil(JSFunction.construct(from: object)) - XCTAssertNotNil(JSFunction.construct(from: function)) - XCTAssertNil(JSFunction.construct(from: symbol)) - XCTAssertNil(JSFunction.construct(from: bigInt)) - XCTAssertNil(JSSymbol.construct(from: object)) XCTAssertNil(JSSymbol.construct(from: function)) XCTAssertNotNil(JSSymbol.construct(from: symbol)) @@ -529,5 +523,9 @@ class JavaScriptKitTests: XCTestCase { } } +#if arch(wasm32) @_extern(c, "llvm.wasm.memory.grow.i32") func growMemory(_ memory: Int32, _ pages: Int32) -> Int32 +#else +func growMemory(_ memory: Int32, _ pages: Int32) -> Int32 { return 0 } +#endif diff --git a/Tests/prelude.mjs b/Tests/prelude.mjs index 88de303a0..e55266e9c 100644 --- a/Tests/prelude.mjs +++ b/Tests/prelude.mjs @@ -1,12 +1,59 @@ // @ts-check +import { + DirectionValues, StatusValues, ThemeValues, HttpStatusValues, TSDirection, TSTheme, APIResultValues, ComplexResultValues, APIOptionalResultValues, StaticCalculatorValues, StaticPropertyEnumValues, PrecisionValues, TypedPayloadResultValues, AllTypesResultValues, OptionalAllTypesResultValues +} from '../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.js'; +import { ImportedFoo } from './BridgeJSRuntimeTests/JavaScript/Types.mjs'; +import { runJsOptionalSupportTests } from './BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs'; +import { getImports as getClosureSupportImports } from './BridgeJSRuntimeTests/JavaScript/ClosureSupportTests.mjs'; +import { getImports as getSwiftClassSupportImports } from './BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs'; +import { getImports as getOptionalSupportImports } from './BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs'; + /** @type {import('../.build/plugins/PackageToJS/outputs/PackageTests/test.d.ts').SetupOptionsFn} */ export async function setupOptions(options, context) { Error.stackTraceLimit = 100; setupTestGlobals(globalThis); + + class StaticBox { + constructor(value) { + this._value = value; + } + value() { + return this._value; + } + static create(value) { + return new StaticBox(value); + } + static value() { + return 99; + } + static makeDefault() { + return new StaticBox(0); + } + static ["with-dashes"]() { + return new StaticBox(7); + } + } + return { ...options, getImports: (importsContext) => { + const ArrayHost = class { + constructor(numbers, labels) { + this.numbers = numbers; + this.labels = labels; + } + concatNumbers(values) { + return [...this.numbers, ...values]; + } + concatLabels(values) { + return [...this.labels, ...values]; + } + firstLabel(values) { + const merged = [...values, ...this.labels]; + return merged.length > 0 ? merged[0] : ""; + } + }; return { "jsRoundTripVoid": () => { return; @@ -20,6 +67,45 @@ export async function setupOptions(options, context) { "jsRoundTripString": (v) => { return v; }, + "jsRoundTripDictionary": (dict) => { + return { ...dict }; + }, + "jsRoundTripDictionaryBool": (dict) => { + return { ...dict }; + }, + "jsRoundTripDictionaryDouble": (dict) => { + return { ...dict }; + }, + "jsRoundTripDictionaryJSObject": (dict) => { + return dict; + }, + "jsRoundTripDictionaryJSValue": (dict) => { + return dict; + }, + "jsRoundTripNestedDictionary": (dict) => { + return Object.fromEntries(Object.entries(dict).map(([k, v]) => [k, [...v]])); + }, + "jsRoundTripOptionalDictionary": (dict) => { + return dict ?? null; + }, + "jsRoundTripUndefinedDictionary": (dict) => { + return dict; + }, + "jsRoundTripJSValue": (v) => { + return v; + }, + "jsRoundTripJSValueArray": (values) => { + return values; + }, + "jsRoundTripOptionalJSValueArray": (values) => { + return values ?? null; + }, + "jsRoundTripIntArray": (items) => { + return items; + }, + "jsArrayLength": (items) => { + return items.length; + }, "jsThrowOrVoid": (shouldThrow) => { if (shouldThrow) { throw new Error("TestError"); @@ -43,6 +129,19 @@ export async function setupOptions(options, context) { } return "Hello, world!"; }, + "jsRoundTripFeatureFlag": (flag) => { + return flag; + }, + "jsEchoJSValue": (v) => { + return v; + }, + "$jsWeirdFunction": () => { + return 42; + }, + ArrayHost, + makeArrayHost: (numbers, labels) => { + return new ArrayHost(numbers, labels); + }, JsGreeter: class { /** * @param {string} name @@ -60,6 +159,15 @@ export async function setupOptions(options, context) { this.name = name; } }, + $WeirdClass: class { + constructor() { + } + ["method-with-dashes"]() { + return "ok"; + } + }, + StaticBox, + Foo: ImportedFoo, runAsyncWorks: async () => { const exports = importsContext.getExports(); if (!exports) { @@ -67,7 +175,36 @@ export async function setupOptions(options, context) { } BridgeJSRuntimeTests_runAsyncWorks(exports); return; - } + }, + jsTranslatePoint: (point, dx, dy) => { + return { x: (point.x | 0) + (dx | 0), y: (point.y | 0) + (dy | 0) }; + }, + jsRoundTripNumberArray: (values) => { + return values; + }, + jsRoundTripStringArray: (values) => { + return values; + }, + jsRoundTripBoolArray: (values) => { + return values; + }, + jsSumNumberArray: (values) => { + return values.reduce((a, b) => a + b, 0); + }, + jsCreateNumberArray: () => { + return [1, 2, 3, 4, 5]; + }, + roundTripArrayMembers: (value) => { + return value; + }, + runJsOptionalSupportTests: () => { + const exports = importsContext.getExports(); + if (!exports) { throw new Error("No exports!?"); } + runJsOptionalSupportTests(exports); + }, + ClosureSupportImports: getClosureSupportImports(importsContext), + SwiftClassSupportImports: getSwiftClassSupportImports(importsContext), + OptionalSupportImports: getOptionalSupportImports(importsContext), }; }, addToCoreImports(importObject, importsContext) { @@ -84,7 +221,19 @@ 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(); + } importObject["BridgeJSRuntimeTests"] = bridgeJSRuntimeTests; + importObject["BridgeJSGlobalTests"] = bridgeJSGlobalTests; } } } @@ -97,6 +246,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, @@ -128,20 +280,262 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { ]) { assert.equal(exports.roundTripString(v), v); } + const dict = { a: 1, b: 2 }; + assert.deepEqual(exports.roundTripDictionaryExport(dict), dict); + const optDict = { hello: "world" }; + assert.deepEqual(exports.roundTripOptionalDictionaryExport(optDict), optDict); + assert.equal(exports.roundTripOptionalDictionaryExport(null), null); + const arrayStruct = { ints: [1, 2, 3], optStrings: ["a", "b"] }; + const arrayStructRoundTrip = exports.roundTripArrayMembers(arrayStruct); + assert.deepEqual(arrayStructRoundTrip.ints, [1, 2, 3]); + assert.deepEqual(arrayStructRoundTrip.optStrings, ["a", "b"]); + assert.equal(exports.arrayMembersSum(arrayStruct, [10, 20]), 30); + assert.equal(exports.arrayMembersFirst(arrayStruct, ["x", "y"]), "x"); + const jsValueArray = [true, 42, "ok", { nested: 1 }, null, undefined]; + assert.deepEqual(exports.roundTripJSValueArray(jsValueArray), jsValueArray); + assert.deepEqual(exports.roundTripOptionalJSValueArray(jsValueArray), jsValueArray); + assert.equal(exports.roundTripOptionalJSValueArray(null), null); + + 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!"); - g.changeName("Jane"); + + // Test property getters + assert.equal(g.name, "John"); + assert.equal(g.prefix, "Hello"); + + // Test property setters + g.name = "Jane"; + assert.equal(g.name, "Jane"); assert.equal(g.greet(), "Hello, Jane!"); - exports.takeGreeter(g, "Jay"); + + // Test readonly property (should still be readable) + assert.equal(g.prefix, "Hello"); + + // Test method-based name change still works + g.changeName("Jay"); + assert.equal(g.name, "Jay"); assert.equal(g.greet(), "Hello, Jay!"); + // Test that property changes via JS are reflected in Swift methods + g.name = "Alice"; + assert.equal(g.greet(), "Hello, Alice!"); + exports.takeGreeter(g, "Bob"); + assert.equal(g.name, "Bob"); + assert.equal(g.greet(), "Hello, Bob!"); + const g2 = exports.roundTripSwiftHeapObject(g) - assert.equal(g2.greet(), "Hello, Jay!"); + assert.equal(g2.greet(), "Hello, Bob!"); + assert.equal(g2.name, "Bob"); + assert.equal(g2.prefix, "Hello"); g2.release(); + // release should be idempotent + const g3 = new exports.Greeter("Idempotent"); + g3.release(); + g3.release(); + g.release(); + const foo = exports.makeImportedFoo("hello"); + assert.ok(foo instanceof ImportedFoo); + assert.equal(foo.value, "hello"); + + // Test PropertyHolder with various types + const testObj = { testProp: "test" }; + const sibling = new exports.SimplePropertyHolder(999); + const ph = new exports.PropertyHolder( + 123, // intValue + 3.14, // floatValue + 2.718, // doubleValue + true, // boolValue + "test", // stringValue + testObj, // jsObject + sibling // sibling + ); + + // Test primitive property getters + assert.equal(ph.intValue, 123); + assert.equal(ph.floatValue, 3.140000104904175); // Float32 precision + assert.equal(ph.doubleValue, 2.718); + assert.equal(ph.boolValue, true); + assert.equal(ph.stringValue, "test"); + + // Test readonly property getters + assert.equal(ph.readonlyInt, 42); + assert.equal(ph.readonlyFloat, 3.140000104904175); // Float32 precision + assert.equal(ph.readonlyDouble, 2.718281828); + assert.equal(ph.readonlyBool, true); + assert.equal(ph.readonlyString, "constant"); + + // Test JSObject property + assert.equal(ph.jsObject, testObj); + + // Test SwiftHeapObject property (sibling should be a SimplePropertyHolder with value 999) + assert.equal(ph.sibling.value, 999); + + // Test primitive property setters + ph.intValue = 456; + ph.floatValue = 6.28; + ph.doubleValue = 1.414; + ph.boolValue = false; + ph.stringValue = "updated"; + + assert.equal(ph.intValue, 456); + assert.equal(ph.floatValue, 6.280000209808350); // Float32 precision + assert.equal(ph.doubleValue, 1.414); + assert.equal(ph.boolValue, false); + assert.equal(ph.stringValue, "updated"); + + // Test JSObject property setter + const newObj = { newProp: "new" }; + ph.jsObject = newObj; + assert.equal(ph.jsObject, newObj); + + // Test SwiftHeapObject property with different object + const ph2 = exports.createPropertyHolder(999, 1.1, 2.2, false, "other", testObj); + const newSibling = new exports.SimplePropertyHolder(123); + ph.sibling = newSibling; + assert.equal(ph.sibling.value, 123); + + // Test lazy property + assert.equal(ph.lazyValue, "computed lazily"); + ph.lazyValue = "modified lazy"; + assert.equal(ph.lazyValue, "modified lazy"); + + // Test computed read-write property + assert.equal(ph.computedReadWrite, "Value: 456"); + ph.computedReadWrite = "Value: 777"; + assert.equal(ph.intValue, 777); // Should have parsed and set intValue + assert.equal(ph.computedReadWrite, "Value: 777"); + + // Test computed readonly property + assert.equal(ph.computedReadonly, 1554); // intValue * 2 = 777 * 2 + + // Test property with observers + // Sync observedProperty to match current intValue, then reset counters for clean test + ph.observedProperty = 777; // Sync with current intValue after computed property changed it + exports.resetObserverCounts(); // Reset counters to start fresh test + + // Set property from JavaScript and verify observers are called + ph.observedProperty = 100; + assert.equal(ph.observedProperty, 100); + let afterSetStats = exports.getObserverStats(); + + // Verify willSet and didSet were called + // The stats should show: willSet:1,didSet:1,willSetOld:777,willSetNew:100,didSetOld:777,didSetNew:100 + assert(afterSetStats.includes("willSet:1"), `willSet should be called once, got: ${afterSetStats}`); + assert(afterSetStats.includes("didSet:1"), `didSet should be called once, got: ${afterSetStats}`); + assert(afterSetStats.includes("willSetOld:777"), `willSet should see old value 777, got: ${afterSetStats}`); + assert(afterSetStats.includes("willSetNew:100"), `willSet should see new value 100, got: ${afterSetStats}`); + assert(afterSetStats.includes("didSetOld:777"), `didSet should see old value 777, got: ${afterSetStats}`); + assert(afterSetStats.includes("didSetNew:100"), `didSet should see new value 100, got: ${afterSetStats}`); + + // Set property to a different value and verify observers are called again + ph.observedProperty = 200; + assert.equal(ph.observedProperty, 200); + let afterSecondSetStats = exports.getObserverStats(); + + // Now should be: willSet:2,didSet:2,willSetOld:100,willSetNew:200,didSetOld:100,didSetNew:200 + assert(afterSecondSetStats.includes("willSet:2"), `willSet should be called twice, got: ${afterSecondSetStats}`); + assert(afterSecondSetStats.includes("didSet:2"), `didSet should be called twice, got: ${afterSecondSetStats}`); + assert(afterSecondSetStats.includes("willSetOld:100"), `willSet should see old value 100 on second call, got: ${afterSecondSetStats}`); + assert(afterSecondSetStats.includes("willSetNew:200"), `willSet should see new value 200 on second call, got: ${afterSecondSetStats}`); + assert(afterSecondSetStats.includes("didSetOld:100"), `didSet should see old value 100 on second call, got: ${afterSecondSetStats}`); + assert(afterSecondSetStats.includes("didSetNew:200"), `didSet should see new value 200 on second call, got: ${afterSecondSetStats}`); + + ph.release(); + ph2.release(); + + // Test static properties + assert.equal(exports.StaticPropertyHolder.staticConstant, "constant"); + assert.equal(exports.StaticPropertyHolder.staticVariable, 42); + assert.equal(exports.StaticPropertyHolder.staticString, "initial"); + assert.equal(exports.StaticPropertyHolder.staticBool, true); + assert.equal(exports.StaticPropertyHolder.staticFloat, 3.140000104904175); + assert.equal(exports.StaticPropertyHolder.staticDouble, 2.718); + assert.equal(exports.StaticPropertyHolder.readOnlyComputed, 84); // staticVariable * 2 = 42 * 2 + + // Test static primitive property setters + exports.StaticPropertyHolder.staticVariable = 200; + exports.StaticPropertyHolder.staticString = "updated"; + exports.StaticPropertyHolder.staticBool = false; + exports.StaticPropertyHolder.staticFloat = 6.28; + exports.StaticPropertyHolder.staticDouble = 1.414; + + assert.equal(exports.StaticPropertyHolder.staticVariable, 200); + assert.equal(exports.StaticPropertyHolder.staticString, "updated"); + assert.equal(exports.StaticPropertyHolder.staticBool, false); + assert.equal(exports.StaticPropertyHolder.staticFloat, 6.280000209808350); + assert.equal(exports.StaticPropertyHolder.staticDouble, 1.414); + + // Test static JSObject + const testStaticObj = { staticTest: "object" }; + exports.StaticPropertyHolder.jsObjectProperty = testStaticObj; + assert.equal(exports.StaticPropertyHolder.jsObjectProperty, testStaticObj); + + const newStaticObj = { newStaticProp: "new" }; + exports.StaticPropertyHolder.jsObjectProperty = newStaticObj; + assert.equal(exports.StaticPropertyHolder.jsObjectProperty, newStaticObj); + + // Test static optional properties + assert.equal(exports.StaticPropertyHolder.optionalString, null); + assert.equal(exports.StaticPropertyHolder.optionalInt, null); + exports.StaticPropertyHolder.optionalString = "optional value"; + exports.StaticPropertyHolder.optionalInt = 42; + assert.equal(exports.StaticPropertyHolder.optionalString, "optional value"); + assert.equal(exports.StaticPropertyHolder.optionalInt, 42); + exports.StaticPropertyHolder.optionalString = null; + exports.StaticPropertyHolder.optionalInt = null; + assert.equal(exports.StaticPropertyHolder.optionalString, null); + assert.equal(exports.StaticPropertyHolder.optionalInt, null); + + // Test static computed properties + assert.equal(exports.StaticPropertyHolder.computedProperty, "computed: 200"); + exports.StaticPropertyHolder.computedProperty = "computed: 300"; // Should have parsed and set staticVariable + assert.equal(exports.StaticPropertyHolder.staticVariable, 300); + assert.equal(exports.StaticPropertyHolder.computedProperty, "computed: 300"); + assert.equal(exports.StaticPropertyHolder.readOnlyComputed, 600); // staticVariable * 2 = 300 * 2 + + // Test static properties in enums + assert.equal(exports.StaticPropertyEnum.enumProperty, "enum value"); + assert.equal(exports.StaticPropertyEnum.enumConstant, 42); + assert.equal(exports.StaticPropertyEnum.enumBool, false); + + exports.StaticPropertyEnum.enumProperty = "modified enum"; + exports.StaticPropertyEnum.enumBool = true; + assert.equal(exports.StaticPropertyEnum.enumProperty, "modified enum"); + assert.equal(exports.StaticPropertyEnum.enumBool, true); + + assert.equal(exports.StaticPropertyEnum.enumVariable, 200); + assert.equal(exports.StaticPropertyEnum.computedReadonly, 400); + assert.equal(exports.StaticPropertyEnum.computedReadWrite, "Value: 200"); + exports.StaticPropertyEnum.computedReadWrite = "Value: 500"; + assert.equal(exports.StaticPropertyEnum.enumVariable, 500); + + // Namespace enum static properties + assert.equal(exports.StaticPropertyNamespace.namespaceProperty, "namespace"); + assert.equal(exports.StaticPropertyNamespace.namespaceConstant, "constant"); + + exports.StaticPropertyNamespace.namespaceProperty = "modified namespace"; + assert.equal(exports.StaticPropertyNamespace.namespaceProperty, "modified namespace"); + + assert.equal(exports.StaticPropertyNamespace.NestedProperties.nestedProperty, 999); + assert.equal(exports.StaticPropertyNamespace.NestedProperties.nestedConstant, "nested"); + assert.equal(exports.StaticPropertyNamespace.NestedProperties.nestedDouble, 1.414); + + exports.StaticPropertyNamespace.NestedProperties.nestedProperty = 1000; + exports.StaticPropertyNamespace.NestedProperties.nestedDouble = 2.828; + assert.equal(exports.StaticPropertyNamespace.NestedProperties.nestedProperty, 1000); + assert.equal(exports.StaticPropertyNamespace.NestedProperties.nestedDouble, 2.828); + // Test class without @JS init constructor const calc = exports.createCalculator(); assert.equal(calc.square(5), 25); @@ -153,6 +547,20 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { const anyObject = {}; assert.equal(exports.roundTripJSObject(anyObject), anyObject); + const symbolValue = Symbol("roundTrip"); + const bigIntValue = 12345678901234567890n; + const objectValue = { nested: true }; + const jsValues = [true, 42, "hello", objectValue, null, undefined, symbolValue, bigIntValue]; + for (const value of jsValues) { + const result = exports.roundTripJSValue(value); + assert.strictEqual(result, value); + } + + assert.strictEqual(exports.roundTripOptionalJSValue(null), null); + assert.strictEqual(exports.roundTripOptionalJSValue(undefined), null); + assert.strictEqual(exports.roundTripOptionalJSValue(objectValue), objectValue); + assert.strictEqual(exports.roundTripOptionalJSValue(symbolValue), symbolValue); + try { exports.throwsSwiftError(true); assert.fail("Expected error"); @@ -165,6 +573,517 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { } catch (error) { assert.fail("Expected no error"); } + + // Test enums + assert.equal(exports.Direction.North, 0); + assert.equal(exports.Direction.South, 1); + assert.equal(exports.Direction.East, 2); + assert.equal(DirectionValues.West, 3); + assert.equal(exports.Status.Loading, 0); + assert.equal(exports.Status.Success, 1); + assert.equal(StatusValues.Error, 2); + + assert.equal(exports.setDirection(exports.Direction.North), DirectionValues.North); + assert.equal(exports.setDirection(exports.Direction.South), exports.Direction.South); + assert.equal(exports.getDirection(), exports.Direction.North); + assert.equal(exports.processDirection(exports.Direction.North), exports.Status.Success); + assert.equal(exports.processDirection(DirectionValues.East), StatusValues.Loading); + + assert.equal(exports.Theme.Light, "light"); + assert.equal(exports.Theme.Dark, "dark"); + assert.equal(ThemeValues.Auto, "auto"); + assert.equal(exports.HttpStatus.Ok, 200); + assert.equal(exports.HttpStatus.NotFound, 404); + 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); + assert.equal(exports.setHttpStatus(exports.HttpStatus.Ok), HttpStatusValues.Ok); + assert.equal(exports.getHttpStatus(), exports.HttpStatus.Ok); + assert.equal(exports.processTheme(exports.Theme.Light), exports.HttpStatus.Ok); + assert.equal(exports.processTheme(exports.Theme.Dark), HttpStatusValues.NotFound); + + assert.equal(TSDirection.North, 0); + assert.equal(TSDirection.South, 1); + assert.equal(TSDirection.East, 2); + assert.equal(TSDirection.West, 3); + assert.equal(TSTheme.Light, "light"); + assert.equal(TSTheme.Dark, "dark"); + assert.equal(TSTheme.Auto, "auto"); + + assert.equal(exports.setTSDirection(TSDirection.North), TSDirection.North); + assert.equal(exports.getTSDirection(), TSDirection.North); + assert.equal(exports.setTSTheme(TSTheme.Light), TSTheme.Light); + assert.equal(exports.getTSTheme(), TSTheme.Light); + + assert.equal(exports.Networking.API.Method.Get, 0); + assert.equal(exports.Networking.API.Method.Post, 1); + assert.equal(exports.Networking.API.Method.Put, 2); + assert.equal(exports.Networking.API.Method.Delete, 3); + assert.equal(exports.Configuration.LogLevel.Debug, "debug"); + assert.equal(exports.Configuration.LogLevel.Info, "info"); + assert.equal(exports.Configuration.LogLevel.Warning, "warning"); + assert.equal(exports.Configuration.LogLevel.Error, "error"); + assert.equal(exports.Configuration.Port.Http, 80); + assert.equal(exports.Configuration.Port.Https, 443); + assert.equal(exports.Configuration.Port.Development, 3000); + assert.equal(exports.Networking.APIV2.Internal.SupportedMethod.Get, 0); + assert.equal(exports.Networking.APIV2.Internal.SupportedMethod.Post, 1); + + assert.equal(exports.roundtripNetworkingAPIMethod(exports.Networking.API.Method.Get), exports.Networking.API.Method.Get); + assert.equal(exports.roundtripConfigurationLogLevel(exports.Configuration.LogLevel.Debug), exports.Configuration.LogLevel.Debug); + assert.equal(exports.roundtripConfigurationPort(exports.Configuration.Port.Http), exports.Configuration.Port.Http); + assert.equal(exports.processConfigurationLogLevel(exports.Configuration.LogLevel.Debug), exports.Configuration.Port.Development); + assert.equal(exports.processConfigurationLogLevel(exports.Configuration.LogLevel.Info), exports.Configuration.Port.Http); + assert.equal(exports.processConfigurationLogLevel(exports.Configuration.LogLevel.Warning), exports.Configuration.Port.Https); + assert.equal(exports.roundtripInternalSupportedMethod(exports.Networking.APIV2.Internal.SupportedMethod.Get), exports.Networking.APIV2.Internal.SupportedMethod.Get); + + const converter = new exports.Utils.Converter(); + assert.equal(converter.toString(42), "42"); + assert.equal(converter.toString(123), "123"); + converter.release(); + + assert.equal(exports.Utils.StringUtils.uppercase("hello"), "HELLO"); + assert.equal(exports.Utils.StringUtils.uppercase(""), ""); + assert.equal(exports.Utils.StringUtils.lowercase("WORLD"), "world"); + assert.equal(exports.Utils.StringUtils.lowercase("HeLLo"), "hello"); + + const httpServer = new exports.Networking.API.HTTPServer(); + httpServer.call(exports.Networking.API.Method.Get); + httpServer.call(exports.Networking.API.Method.Post); + httpServer.release(); + + const testServer = new exports.Networking.APIV2.Internal.TestServer(); + testServer.call(exports.Networking.APIV2.Internal.SupportedMethod.Get); + testServer.call(exports.Networking.APIV2.Internal.SupportedMethod.Post); + testServer.release(); + + const s1 = { tag: exports.APIResult.Tag.Success, param0: "Cześć 🙋‍♂️" }; + const f1 = { tag: exports.APIResult.Tag.Failure, param0: 42 }; + const i1 = { tag: APIResultValues.Tag.Info }; + + assert.deepEqual(exports.roundtripAPIResult(s1), s1); + assert.deepEqual(exports.roundtripAPIResult(f1), f1); + assert.deepEqual(exports.roundtripAPIResult(i1), i1); + + assert.deepEqual(exports.makeAPIResultSuccess("Test"), { tag: exports.APIResult.Tag.Success, param0: "Test" }); + assert.deepEqual(exports.makeAPIResultSuccess("ok"), { tag: exports.APIResult.Tag.Success, param0: "ok" }); + assert.deepEqual(exports.makeAPIResultFailure(123), { tag: exports.APIResult.Tag.Failure, param0: 123 }); + assert.deepEqual(exports.makeAPIResultInfo(), { tag: APIResultValues.Tag.Info }); + + const bTrue = { tag: exports.APIResult.Tag.Flag, param0: true }; + const bFalse = { tag: exports.APIResult.Tag.Flag, param0: false }; + assert.deepEqual(exports.makeAPIResultFlag(true), bTrue); + assert.deepEqual(exports.makeAPIResultFlag(false), bFalse); + + const rVal = 3.25; + const r1 = { tag: exports.APIResult.Tag.Rate, param0: rVal }; + assert.deepEqual(exports.roundtripAPIResult(r1), r1); + assert.deepEqual(exports.makeAPIResultRate(rVal), r1); + + const pVal = 3.141592653589793; + const p1 = { tag: APIResultValues.Tag.Precise, param0: pVal }; + assert.deepEqual(exports.roundtripAPIResult(p1), p1); + assert.deepEqual(exports.makeAPIResultPrecise(pVal), p1); + + const cs1 = { tag: exports.ComplexResult.Tag.Success, param0: "All good!" }; + const ce1 = { tag: exports.ComplexResult.Tag.Error, param0: "Network error", param1: 503 }; + const cl1 = { tag: exports.ComplexResult.Tag.Location, param0: 37.7749, param1: -122.4194, param2: "San Francisco" }; + const cst1 = { tag: exports.ComplexResult.Tag.Status, param0: true, param1: 200, param2: "OK" }; + const cc1 = { tag: exports.ComplexResult.Tag.Coordinates, param0: 10.5, param1: 20.3, param2: 30.7 }; + const ccomp1 = { tag: ComplexResultValues.Tag.Comprehensive, param0: true, param1: false, param2: 42, param3: 100, param4: 3.14, param5: 2.718, param6: "Hello", param7: "World", param8: "Test" }; + const ci1 = { tag: ComplexResultValues.Tag.Info }; + + assert.deepEqual(exports.roundtripComplexResult(cs1), cs1); + assert.deepEqual(exports.roundtripComplexResult(ce1), ce1); + assert.deepEqual(exports.roundtripComplexResult(cl1), cl1); + assert.deepEqual(exports.roundtripComplexResult(cst1), cst1); + assert.deepEqual(exports.roundtripComplexResult(cc1), cc1); + assert.deepEqual(exports.roundtripComplexResult(ccomp1), ccomp1); + assert.deepEqual(exports.roundtripComplexResult(ci1), ci1); + + assert.deepEqual(exports.makeComplexResultSuccess("Great!"), { tag: exports.ComplexResult.Tag.Success, param0: "Great!" }); + assert.deepEqual(exports.makeComplexResultError("Timeout", 408), { tag: exports.ComplexResult.Tag.Error, param0: "Timeout", param1: 408 }); + assert.deepEqual(exports.makeComplexResultLocation(40.7128, -74.0060, "New York"), { tag: exports.ComplexResult.Tag.Location, param0: 40.7128, param1: -74.0060, param2: "New York" }); + assert.deepEqual(exports.makeComplexResultStatus(false, 500, "Internal Server Error"), { tag: exports.ComplexResult.Tag.Status, param0: false, param1: 500, param2: "Internal Server Error" }); + assert.deepEqual(exports.makeComplexResultCoordinates(1.1, 2.2, 3.3), { tag: exports.ComplexResult.Tag.Coordinates, param0: 1.1, param1: 2.2, param2: 3.3 }); + assert.deepEqual(exports.makeComplexResultComprehensive(true, false, 10, 20, 1.5, 2.5, "First", "Second", "Third"), { tag: exports.ComplexResult.Tag.Comprehensive, param0: true, param1: false, param2: 10, param3: 20, param4: 1.5, param5: 2.5, param6: "First", param7: "Second", param8: "Third" }); + assert.deepEqual(exports.makeComplexResultInfo(), { tag: exports.ComplexResult.Tag.Info }); + + const urSuccess = { tag: exports.Utilities.Result.Tag.Success, param0: "Utility operation completed" }; + const urFailure = { tag: exports.Utilities.Result.Tag.Failure, param0: "Utility error occurred", param1: 500 }; + const urStatus = { tag: exports.Utilities.Result.Tag.Status, param0: true, param1: 200, param2: "Utility status OK" }; + + assert.deepEqual(exports.roundtripUtilitiesResult(urSuccess), urSuccess); + assert.deepEqual(exports.roundtripUtilitiesResult(urFailure), urFailure); + assert.deepEqual(exports.roundtripUtilitiesResult(urStatus), urStatus); + + assert.deepEqual(exports.makeUtilitiesResultSuccess("Test"), { tag: exports.Utilities.Result.Tag.Success, param0: "Test" }); + assert.deepEqual(exports.makeUtilitiesResultSuccess("ok"), { tag: exports.Utilities.Result.Tag.Success, param0: "ok" }); + assert.deepEqual(exports.makeUtilitiesResultFailure("Error", 123), { tag: exports.Utilities.Result.Tag.Failure, param0: "Error", param1: 123 }); + assert.deepEqual(exports.makeUtilitiesResultStatus(true, 200, "OK"), { tag: exports.Utilities.Result.Tag.Status, param0: true, param1: 200, param2: "OK" }); + + const nrSuccess = { tag: exports.API.NetworkingResult.Tag.Success, param0: "Network request successful" }; + const nrFailure = { tag: exports.API.NetworkingResult.Tag.Failure, param0: "Network timeout", param1: 408 }; + + assert.deepEqual(exports.roundtripAPINetworkingResult(nrSuccess), nrSuccess); + assert.deepEqual(exports.roundtripAPINetworkingResult(nrFailure), nrFailure); + + assert.deepEqual(exports.makeAPINetworkingResultSuccess("Connected"), { tag: exports.API.NetworkingResult.Tag.Success, param0: "Connected" }); + assert.deepEqual(exports.makeAPINetworkingResultFailure("Timeout", 408), { tag: exports.API.NetworkingResult.Tag.Failure, param0: "Timeout", param1: 408 }); + + // TypedPayloadResult — rawValueEnum and caseEnum as associated value payloads + assert.equal(exports.Precision.Rough, 0.1); + assert.equal(exports.Precision.Fine, 0.001); + + const tpr_precision = { tag: exports.TypedPayloadResult.Tag.Precision, param0: Math.fround(0.1) }; + assert.deepEqual(exports.roundTripTypedPayloadResult(tpr_precision), tpr_precision); + + const tpr_direction = { tag: exports.TypedPayloadResult.Tag.Direction, param0: exports.Direction.North }; + assert.deepEqual(exports.roundTripTypedPayloadResult(tpr_direction), tpr_direction); + + const tpr_dirSouth = { tag: exports.TypedPayloadResult.Tag.Direction, param0: exports.Direction.South }; + assert.deepEqual(exports.roundTripTypedPayloadResult(tpr_dirSouth), tpr_dirSouth); + + const tpr_optPrecisionSome = { tag: exports.TypedPayloadResult.Tag.OptPrecision, param0: Math.fround(0.001) }; + assert.deepEqual(exports.roundTripTypedPayloadResult(tpr_optPrecisionSome), tpr_optPrecisionSome); + + const tpr_optPrecisionNull = { tag: exports.TypedPayloadResult.Tag.OptPrecision, param0: null }; + assert.deepEqual(exports.roundTripTypedPayloadResult(tpr_optPrecisionNull), tpr_optPrecisionNull); + + const tpr_optDirectionSome = { tag: exports.TypedPayloadResult.Tag.OptDirection, param0: exports.Direction.East }; + assert.deepEqual(exports.roundTripTypedPayloadResult(tpr_optDirectionSome), tpr_optDirectionSome); + + const tpr_optDirectionNull = { tag: exports.TypedPayloadResult.Tag.OptDirection, param0: null }; + assert.deepEqual(exports.roundTripTypedPayloadResult(tpr_optDirectionNull), tpr_optDirectionNull); + + const tpr_empty = { tag: exports.TypedPayloadResult.Tag.Empty }; + assert.deepEqual(exports.roundTripTypedPayloadResult(tpr_empty), tpr_empty); + + // AllTypesResult — struct, class, JSObject, nested enum, array as associated value payloads + const atr_struct = { tag: AllTypesResultValues.Tag.StructPayload, param0: { street: "100 Main St", city: "Boston", zipCode: 2101 } }; + assert.deepEqual(exports.roundTripAllTypesResult(atr_struct), atr_struct); + + const atr_class = { tag: AllTypesResultValues.Tag.ClassPayload, param0: new exports.Greeter("EnumUser") }; + const atr_class_result = exports.roundTripAllTypesResult(atr_class); + assert.equal(atr_class_result.tag, AllTypesResultValues.Tag.ClassPayload); + assert.equal(atr_class_result.param0.name, "EnumUser"); + + const atr_jsObject = { tag: AllTypesResultValues.Tag.JsObjectPayload, param0: { custom: "data", value: 42 } }; + const atr_jsObject_result = exports.roundTripAllTypesResult(atr_jsObject); + assert.equal(atr_jsObject_result.tag, AllTypesResultValues.Tag.JsObjectPayload); + assert.equal(atr_jsObject_result.param0.custom, "data"); + assert.equal(atr_jsObject_result.param0.value, 42); + + const atr_nestedEnum = { tag: AllTypesResultValues.Tag.NestedEnum, param0: { tag: APIResultValues.Tag.Success, param0: "nested!" } }; + assert.deepEqual(exports.roundTripAllTypesResult(atr_nestedEnum), atr_nestedEnum); + + const atr_array = { tag: AllTypesResultValues.Tag.ArrayPayload, param0: [10, 20, 30] }; + assert.deepEqual(exports.roundTripAllTypesResult(atr_array), atr_array); + + const atr_jsClass = { tag: AllTypesResultValues.Tag.JsClassPayload, param0: new ImportedFoo("enumFoo") }; + const atr_jsClass_result = exports.roundTripAllTypesResult(atr_jsClass); + assert.equal(atr_jsClass_result.tag, AllTypesResultValues.Tag.JsClassPayload); + assert.equal(atr_jsClass_result.param0.value, "enumFoo"); + + const atr_empty = { tag: AllTypesResultValues.Tag.Empty }; + assert.deepEqual(exports.roundTripAllTypesResult(atr_empty), atr_empty); + + assert.equal(exports.MathUtils.add(2147483647, 0), 2147483647); + assert.equal(exports.StaticCalculator.roundtrip(42), 42); + assert.equal(StaticCalculatorValues.Scientific, 0); + assert.equal(StaticCalculatorValues.Basic, 1); + assert.equal(StaticCalculatorValues.Scientific, exports.StaticCalculator.Scientific); + assert.equal(StaticCalculatorValues.Basic, exports.StaticCalculator.Basic); + assert.equal(exports.StaticUtils.Nested.roundtrip("hello world"), "hello world"); + assert.equal(exports.StaticUtils.Nested.roundtrip("test"), "test"); + + assert.equal(exports.Services.Graph.GraphOperations.createGraph(5), 50); + assert.equal(exports.Services.Graph.GraphOperations.createGraph(0), 0); + assert.equal(exports.Services.Graph.GraphOperations.nodeCount(42), 42); + assert.equal(exports.Services.Graph.GraphOperations.nodeCount(0), 0); + + // Test default parameters + assert.equal(exports.testStringDefault(), "Hello World"); + assert.equal(exports.testStringDefault("Custom Message"), "Custom Message"); + + assert.equal(exports.testIntDefault(), 42); + assert.equal(exports.testIntDefault(100), 100); + + assert.equal(exports.testBoolDefault(), true); + assert.equal(exports.testBoolDefault(false), false); + + assert.equal(exports.testOptionalDefault(), null); + assert.equal(exports.testOptionalDefault("Test"), "Test"); + + assert.equal(exports.testMultipleDefaults(), "Default Title: -10 (false)"); + assert.equal(exports.testMultipleDefaults("Custom"), "Custom: -10 (false)"); + assert.equal(exports.testMultipleDefaults("Custom", 5), "Custom: 5 (false)"); + assert.equal(exports.testMultipleDefaults("Custom", undefined, true), "Custom: -10 (true)"); + assert.equal(exports.testMultipleDefaults("Custom", 5, true), "Custom: 5 (true)"); + + assert.equal(exports.testSimpleEnumDefault(), exports.Status.Success); + assert.equal(exports.testSimpleEnumDefault(exports.Status.Loading), exports.Status.Loading); + + assert.equal(exports.testDirectionDefault(), exports.Direction.North); + assert.equal(exports.testDirectionDefault(exports.Direction.South), exports.Direction.South); + + assert.equal(exports.testRawStringEnumDefault(), exports.Theme.Light); + assert.equal(exports.testRawStringEnumDefault(exports.Theme.Dark), exports.Theme.Dark); + + const holder = exports.testEmptyInit() + assert.notEqual(holder, null); + holder.release(); + + const customHolder = new exports.StaticPropertyHolder(); + assert.deepEqual(exports.testEmptyInit(customHolder), customHolder); + customHolder.release(); + + assert.equal(exports.testComplexInit(), "Hello, DefaultGreeter!"); + const customGreeter = new exports.Greeter("CustomName"); + assert.equal(exports.testComplexInit(customGreeter), "Hello, CustomName!"); + + customGreeter.release(); + + const cd1 = new exports.ConstructorDefaults(); + assert.equal(cd1.describe(), "Default:42:true:success:nil"); + cd1.release(); + + const cd2 = new exports.ConstructorDefaults("Custom"); + assert.equal(cd2.describe(), "Custom:42:true:success:nil"); + cd2.release(); + + const cd3 = new exports.ConstructorDefaults("Custom", 100); + assert.equal(cd3.describe(), "Custom:100:true:success:nil"); + cd3.release(); + + const cd4 = new exports.ConstructorDefaults("Custom", undefined, false); + assert.equal(cd4.describe(), "Custom:42:false:success:nil"); + cd4.release(); + + const cd5 = new exports.ConstructorDefaults("Test", 99, false, exports.Status.Loading); + assert.equal(cd5.describe(), "Test:99:false:loading:nil"); + cd5.release(); + + testProtocolSupport(exports); + testArraySupport(exports); +} + +/** @param {import('./../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */ +function testStructSupport(exports) { + const data1 = { x: 1.5, y: 2.5, label: "Point", optCount: 42, optFlag: true }; + assert.deepEqual(exports.roundTripDataPoint(data1), data1); + const data2 = { x: 0.0, y: 0.0, label: "", optCount: null, optFlag: null }; + assert.deepEqual(exports.roundTripDataPoint(data2), data2); + + const publicPoint = { x: 9, y: -3 }; + assert.deepEqual(exports.roundTripPublicPoint(publicPoint), publicPoint); + + const pointerFields1 = { raw: 1, mutRaw: 4, opaque: 1024, ptr: 65536, mutPtr: 2 }; + assert.deepEqual(exports.roundTripPointerFields(pointerFields1), pointerFields1); + + const contact1 = { + name: "Alice", + age: 30, + address: { street: "123 Main St", city: "NYC", zipCode: 10001 }, + email: "alice@test.com", + secondaryAddress: { street: "456 Oak Ave", city: "LA", zipCode: null } + }; + assert.deepEqual(exports.roundTripContact(contact1), contact1); + const contact2 = { + name: "Bob", + age: 25, + address: { street: "789 Pine Rd", city: "SF", zipCode: null }, + email: null, + secondaryAddress: null + }; + assert.deepEqual(exports.roundTripContact(contact2), contact2); + + const config1 = { + name: "prod", + theme: exports.Theme.Dark, + direction: exports.Direction.North, + status: exports.Status.Success + }; + assert.deepEqual(exports.roundTripConfig(config1), config1); + const config2 = { + name: "dev", + theme: null, + direction: null, + status: exports.Status.Loading + }; + assert.deepEqual(exports.roundTripConfig(config2), config2); + + const owner1 = new exports.Greeter("TestUser"); + const session1 = { id: 123, owner: owner1 }; + const resultSession1 = exports.roundTripSessionData(session1); + assert.equal(resultSession1.id, 123); + assert.equal(resultSession1.owner.greet(), "Hello, TestUser!"); + const session2 = { id: 456, owner: null }; + assert.deepEqual(exports.roundTripSessionData(session2), session2); + owner1.release(); + resultSession1.owner.release(); + + const report1 = { + id: 100, + result: { tag: exports.APIResult.Tag.Success, param0: "ok" }, + status: exports.Status.Success, + outcome: { tag: exports.APIResult.Tag.Info } + }; + assert.deepEqual(exports.roundTripValidationReport(report1), report1); + const report2 = { + id: 200, + result: { tag: exports.APIResult.Tag.Failure, param0: 404 }, + status: null, + outcome: null + }; + assert.deepEqual(exports.roundTripValidationReport(report2), report2); + + const origReport = { + id: 999, + result: { tag: exports.APIResult.Tag.Failure, param0: 500 }, + status: exports.Status.Error, + outcome: { tag: exports.APIResult.Tag.Info } + }; + const updatedReport = exports.updateValidationReport( + { tag: exports.APIResult.Tag.Success, param0: "updated" }, + origReport + ); + 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); + assert.equal(mathOps.add(5.0, 3.0), 8.0); + assert.equal(mathOps.multiply(4.0, 7.0), 28.0); + + const mathOps2 = exports.MathOperations.init(100.0); + assert.equal(mathOps2.baseValue, 100.0); + assert.equal(mathOps2.add(5.0, 3.0), 108.0); + + assert.equal(mathOps.add(5.0), 15.0); + assert.equal(mathOps2.add(5.0), 115.0); + + assert.equal(exports.testStructDefault(), "1.0,2.0,default"); + 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); + container.release(); + + assert.equal(exports.ConfigStruct.defaultConfig, "production"); + assert.equal(exports.ConfigStruct.maxRetries, 3); + assert.equal(exports.ConfigStruct.computedSetting, "Config: production"); + 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); + + // Struct with JSObject field + const containerObj1 = { value: "hello", nested: { x: 1 } }; + const containerObj2 = { items: [1, 2, 3] }; + const container1 = { object: containerObj1, optionalObject: containerObj2 }; + const containerResult1 = exports.roundTripJSObjectContainer(container1); + assert.equal(containerResult1.object, containerObj1); + assert.equal(containerResult1.optionalObject, containerObj2); + + const container2 = { object: containerObj1, optionalObject: null }; + const containerResult2 = exports.roundTripJSObjectContainer(container2); + assert.equal(containerResult2.object, containerObj1); + assert.equal(containerResult2.optionalObject, null); + + // Struct with @JSClass field + const foo1 = new ImportedFoo("first"); + const foo2 = new ImportedFoo("second"); + const fooContainer1 = { foo: foo1, optionalFoo: foo2 }; + const fooContainerResult1 = exports.roundTripFooContainer(fooContainer1); + assert.equal(fooContainerResult1.foo.value, "first"); + assert.equal(fooContainerResult1.optionalFoo.value, "second"); + + const fooContainer2 = { foo: foo1, optionalFoo: null }; + const fooContainerResult2 = exports.roundTripFooContainer(fooContainer2); + assert.equal(fooContainerResult2.foo.value, "first"); + assert.equal(fooContainerResult2.optionalFoo, null); } /** @param {import('./../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */ @@ -172,6 +1091,56 @@ 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); + assert.equal(globalThis.GlobalNetworking.API.CallMethodValues.Put, 2); + assert.equal(globalThis.GlobalNetworking.API.CallMethodValues.Delete, 3); + + assert.equal(globalThis.GlobalConfiguration.PublicLogLevelValues.Debug, "debug"); + assert.equal(globalThis.GlobalConfiguration.PublicLogLevelValues.Info, "info"); + assert.equal(globalThis.GlobalConfiguration.PublicLogLevelValues.Warning, "warning"); + assert.equal(globalThis.GlobalConfiguration.PublicLogLevelValues.Error, "error"); + assert.equal(globalThis.GlobalConfiguration.AvailablePortValues.Http, 80); + assert.equal(globalThis.GlobalConfiguration.AvailablePortValues.Https, 443); + assert.equal(globalThis.GlobalConfiguration.AvailablePortValues.Development, 3000); + + assert.equal(globalThis.GlobalNetworking.APIV2.Internal.SupportedServerMethodValues.Get, 0); + assert.equal(globalThis.GlobalNetworking.APIV2.Internal.SupportedServerMethodValues.Post, 1); + + const globalConverter = new globalThis.GlobalUtils.PublicConverter(); + assert.equal(globalConverter.toString(99), "99"); + globalConverter.release(); + + const globalHttpServer = new globalThis.GlobalNetworking.API.TestHTTPServer(); + globalHttpServer.call(globalThis.GlobalNetworking.API.CallMethodValues.Get); + globalHttpServer.release(); + + const globalTestServer = new globalThis.GlobalNetworking.APIV2.Internal.TestInternalServer(); + globalTestServer.call(globalThis.GlobalNetworking.APIV2.Internal.SupportedServerMethodValues.Post); + globalTestServer.release(); + + assert.equal(globalThis.GlobalStaticPropertyNamespace.namespaceProperty, "namespace"); + assert.equal(globalThis.GlobalStaticPropertyNamespace.namespaceConstant, "constant"); + + globalThis.GlobalStaticPropertyNamespace.namespaceProperty = "further modified"; + assert.equal(globalThis.GlobalStaticPropertyNamespace.namespaceProperty, "further modified"); + + assert.equal(globalThis.GlobalStaticPropertyNamespace.NestedProperties.nestedProperty, 999); + assert.equal(globalThis.GlobalStaticPropertyNamespace.NestedProperties.nestedConstant, "nested"); + assert.equal(globalThis.GlobalStaticPropertyNamespace.NestedProperties.nestedDouble, 1.414); + + globalThis.GlobalStaticPropertyNamespace.NestedProperties.nestedProperty = 2000; + globalThis.GlobalStaticPropertyNamespace.NestedProperties.nestedDouble = 3.141; + assert.equal(globalThis.GlobalStaticPropertyNamespace.NestedProperties.nestedProperty, 2000); + assert.equal(globalThis.GlobalStaticPropertyNamespace.NestedProperties.nestedDouble, 3.141); +} + function setupTestGlobals(global) { global.globalObject1 = { prop_1: { @@ -264,3 +1233,437 @@ function setupTestGlobals(global) { bi: BigInt(3) }; } + +/** @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.roundTripUnsafePointerArray(pointerValues), pointerValues); + assert.deepEqual(exports.roundTripUnsafeMutablePointerArray(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(); + + // JSObject arrays + const jsObj1 = { a: 1, b: "hello" }; + const jsObj2 = { x: [1, 2, 3], y: { nested: true } }; + const jsObjResult = exports.roundTripJSObjectArray([jsObj1, jsObj2]); + assert.equal(jsObjResult.length, 2); + assert.equal(jsObjResult[0], jsObj1); + assert.equal(jsObjResult[1], jsObj2); + assert.deepEqual(exports.roundTripJSObjectArray([]), []); + + const optJsResult = exports.roundTripOptionalJSObjectArray([jsObj1, null, jsObj2]); + assert.equal(optJsResult.length, 3); + assert.equal(optJsResult[0], jsObj1); + assert.equal(optJsResult[1], null); + assert.equal(optJsResult[2], jsObj2); + + // @JSClass struct arrays + const foo1 = new ImportedFoo("first"); + const foo2 = new ImportedFoo("second"); + const fooResult = exports.roundTripFooArray([foo1, foo2]); + assert.equal(fooResult.length, 2); + assert.equal(fooResult[0].value, "first"); + assert.equal(fooResult[1].value, "second"); + assert.deepEqual(exports.roundTripFooArray([]), []); + + const optFooResult = exports.roundTripOptionalFooArray([foo1, null, foo2]); + assert.equal(optFooResult.length, 3); + assert.equal(optFooResult[0].value, "first"); + assert.equal(optFooResult[1], null); + assert.equal(optFooResult[2].value, "second"); +} + +/** @param {import('./../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */ +function testProtocolSupport(exports) { + let processorValue = 0; + let processorLabel = ""; + let lastAPIResult = null; + const jsProcessor = { + count: 0, + name: "JSProcessor", + optionalTag: null, + direction: null, + optionalTheme: null, + httpStatus: null, + get apiResult() { return lastAPIResult; }, + set apiResult(value) { lastAPIResult = value; }, + helper: new exports.Greeter("JSHelper"), + optionalHelper: null, + optionalCount: null, + increment(amount) { processorValue += amount; this.count += amount; }, + getValue() { return processorValue; }, + setLabelElements(labelPrefix, labelSuffix) { processorLabel = labelPrefix + labelSuffix; }, + getLabel() { return processorLabel; }, + isEven() { return processorValue % 2 === 0; }, + processGreeter(greeter) { return `JSProcessor processed: ${greeter.greet()}`; }, + createGreeter() { return new exports.Greeter("JSProcessorGreeter"); }, + processOptionalGreeter(greeter) { + return greeter ? `JSProcessor processed optional: ${greeter.greet()}` : "JSProcessor received null"; + }, + createOptionalGreeter() { return new exports.Greeter("JSOptionalGreeter"); }, + handleAPIResult(result) { lastAPIResult = result; }, + getAPIResult() { return lastAPIResult; } + }; + + const successResult = { tag: exports.Utilities.Result.Tag.Success, param0: "Operation completed" }; + const failureResult = { tag: exports.Utilities.Result.Tag.Failure, param0: 500 }; + + const jsManager = new exports.DataProcessorManager(jsProcessor); + + jsManager.incrementByAmount(4); + assert.equal(jsManager.getCurrentValue(), 4); + assert.equal(jsProcessor.count, 4); + + jsManager.setProcessorLabel("Test", "Label"); + assert.equal(jsManager.getProcessorLabel(), "TestLabel"); + + assert.equal(jsManager.isProcessorEven(), true); + jsManager.incrementByAmount(1); + assert.equal(jsManager.isProcessorEven(), false); + + assert.equal(jsManager.getProcessorOptionalTag(), null); + jsManager.setProcessorOptionalTag("test-tag"); + assert.equal(jsManager.getProcessorOptionalTag(), "test-tag"); + jsManager.setProcessorOptionalTag("another-tag"); + assert.equal(jsManager.getProcessorOptionalTag(), "another-tag"); + jsManager.setProcessorOptionalTag(null); + assert.equal(jsManager.getProcessorOptionalTag(), null); + + // Test direct property access for optionalTag + jsProcessor.optionalTag = "direct-tag"; + assert.equal(jsManager.getProcessorOptionalTag(), "direct-tag"); + assert.equal(jsProcessor.optionalTag, "direct-tag"); + jsProcessor.optionalTag = null; + assert.equal(jsManager.getProcessorOptionalTag(), null); + assert.equal(jsProcessor.optionalTag, null); + + assert.equal(jsManager.getProcessorDirection(), null); + jsManager.setProcessorDirection(exports.Direction.North); + assert.equal(jsManager.getProcessorDirection(), exports.Direction.North); + jsManager.setProcessorDirection(exports.Direction.East); + assert.equal(jsManager.getProcessorDirection(), exports.Direction.East); + jsManager.setProcessorDirection(null); + assert.equal(jsManager.getProcessorDirection(), null); + + assert.equal(jsManager.getProcessorTheme(), null); + jsManager.setProcessorTheme(exports.Theme.Light); + assert.equal(jsManager.getProcessorTheme(), exports.Theme.Light); + jsManager.setProcessorTheme(exports.Theme.Dark); + assert.equal(jsManager.getProcessorTheme(), exports.Theme.Dark); + jsManager.setProcessorTheme(null); + assert.equal(jsManager.getProcessorTheme(), null); + + assert.equal(jsManager.getProcessorHttpStatus(), null); + jsManager.setProcessorHttpStatus(exports.HttpStatus.Ok); + assert.equal(jsManager.getProcessorHttpStatus(), exports.HttpStatus.Ok); + jsManager.setProcessorHttpStatus(exports.HttpStatus.NotFound); + assert.equal(jsManager.getProcessorHttpStatus(), exports.HttpStatus.NotFound); + jsManager.setProcessorHttpStatus(null); + assert.equal(jsManager.getProcessorHttpStatus(), null); + + jsProcessor.handleAPIResult(successResult); + assert.deepEqual(jsProcessor.getAPIResult(), successResult); + + jsProcessor.handleAPIResult(failureResult); + assert.deepEqual(jsProcessor.getAPIResult(), failureResult); + + jsProcessor.apiResult = successResult; + assert.deepEqual(jsProcessor.apiResult, successResult); + jsProcessor.apiResult = null; + assert.equal(jsProcessor.apiResult, null); + assert.equal(jsManager.getProcessorAPIResult(), null); + + assert.equal(jsProcessor.helper.name, "JSHelper"); + const newHelper = new exports.Greeter("UpdatedHelper"); + jsProcessor.helper = newHelper; + assert.equal(jsProcessor.helper.name, "UpdatedHelper"); + assert.equal(jsProcessor.helper.greet(), "Hello, UpdatedHelper!"); + + assert.equal(jsProcessor.optionalHelper, null); + const optHelper = new exports.Greeter("OptHelper"); + jsProcessor.optionalHelper = optHelper; + assert.equal(jsProcessor.optionalHelper.name, "OptHelper"); + assert.equal(jsProcessor.optionalHelper.greet(), "Hello, OptHelper!"); + jsProcessor.optionalHelper = null; + assert.equal(jsProcessor.optionalHelper, null); + + assert.equal(jsManager.getProcessorOptionalCount(), null); + jsManager.setProcessorOptionalCount(42); + assert.equal(jsManager.getProcessorOptionalCount(), 42); + jsManager.setProcessorOptionalCount(0); + assert.equal(jsManager.getProcessorOptionalCount(), 0); + jsManager.setProcessorOptionalCount(-100); + assert.equal(jsManager.getProcessorOptionalCount(), -100); + jsManager.setProcessorOptionalCount(null); + assert.equal(jsManager.getProcessorOptionalCount(), null); + + assert.equal(jsProcessor.optionalCount, null); + jsProcessor.optionalCount = 42; + assert.equal(jsProcessor.optionalCount, 42); + assert.equal(jsManager.getProcessorOptionalCount(), 42); + jsProcessor.optionalCount = 0; + assert.equal(jsProcessor.optionalCount, 0); + jsProcessor.optionalCount = null; + assert.equal(jsProcessor.optionalCount, null); + + newHelper.release(); + optHelper.release(); + jsManager.release(); + + const swiftProcessor = new exports.SwiftDataProcessor(); + const swiftManager = new exports.DataProcessorManager(swiftProcessor); + + swiftManager.incrementByAmount(10); + assert.equal(swiftManager.getCurrentValue(), 10); + + swiftManager.setProcessorLabel("Swift", "Label"); + assert.equal(swiftManager.getProcessorLabel(), "SwiftLabel"); + + assert.equal(swiftManager.isProcessorEven(), true); + swiftManager.incrementByAmount(1); + assert.equal(swiftManager.isProcessorEven(), false); + + assert.equal(swiftManager.getProcessorDirection(), null); + swiftManager.setProcessorDirection(exports.Direction.South); + assert.equal(swiftManager.getProcessorDirection(), exports.Direction.South); + swiftManager.setProcessorDirection(exports.Direction.West); + assert.equal(swiftManager.getProcessorDirection(), exports.Direction.West); + swiftManager.setProcessorDirection(null); + assert.equal(swiftManager.getProcessorDirection(), null); + + assert.equal(swiftManager.getProcessorTheme(), null); + swiftProcessor.optionalTheme = exports.Theme.Light; + assert.equal(swiftManager.getProcessorTheme(), exports.Theme.Light); + swiftManager.setProcessorTheme(exports.Theme.Auto); + assert.equal(swiftManager.getProcessorTheme(), exports.Theme.Auto); + swiftManager.setProcessorTheme(exports.Theme.Light); + assert.equal(swiftManager.getProcessorTheme(), exports.Theme.Light); + swiftManager.setProcessorTheme(null); + assert.equal(swiftManager.getProcessorTheme(), null); + + assert.equal(swiftManager.getProcessorHttpStatus(), null); + swiftManager.setProcessorHttpStatus(exports.HttpStatus.ServerError); + assert.equal(swiftManager.getProcessorHttpStatus(), exports.HttpStatus.ServerError); + swiftManager.setProcessorHttpStatus(exports.HttpStatus.Ok); + assert.equal(swiftManager.getProcessorHttpStatus(), exports.HttpStatus.Ok); + swiftManager.setProcessorHttpStatus(null); + assert.equal(swiftManager.getProcessorHttpStatus(), null); + + swiftProcessor.handleAPIResult(successResult); + assert.deepEqual(swiftProcessor.getAPIResult(), successResult); + assert.deepEqual(swiftManager.getProcessorAPIResult(), successResult); + + swiftProcessor.handleAPIResult(failureResult); + assert.deepEqual(swiftProcessor.getAPIResult(), failureResult); + assert.deepEqual(swiftManager.getProcessorAPIResult(), failureResult); + swiftManager.setProcessorAPIResult(successResult); + assert.deepEqual(swiftProcessor.getAPIResult(), successResult); + + swiftManager.release(); + swiftProcessor.release(); + + let backupValue = 100; + const backupProcessor = { + count: 100, + name: "BackupProcessor", + optionalTag: null, + direction: null, + optionalTheme: null, + httpStatus: null, + apiResult: null, + helper: new exports.Greeter("BackupHelper"), + optionalHelper: null, + optionalCount: null, + increment(amount) { backupValue += amount; this.count += amount; }, + getValue() { return backupValue; }, + setLabelElements(labelPrefix, labelSuffix) { }, + getLabel() { return "backup"; }, + isEven() { return backupValue % 2 === 0; }, + processGreeter(greeter) { return ""; }, + createGreeter() { return new exports.Greeter("BackupGreeter"); }, + processOptionalGreeter(greeter) { return ""; }, + createOptionalGreeter() { return null; }, + handleAPIResult(result) { }, + getAPIResult() { return { tag: exports.APIResult.Tag.Info }; } + }; + + let mainValue = 0; + const mainProcessor = { + count: 0, + name: "MainProcessor", + optionalTag: null, + direction: null, + optionalTheme: null, + httpStatus: null, + apiResult: null, + helper: new exports.Greeter("MainHelper"), + optionalHelper: null, + optionalCount: null, + increment(amount) { mainValue += amount; this.count += amount; }, + getValue() { return mainValue; }, + setLabelElements(labelPrefix, labelSuffix) { }, + getLabel() { return "main"; }, + isEven() { return mainValue % 2 === 0; }, + processGreeter(greeter) { return ""; }, + createGreeter() { return new exports.Greeter("MainGreeter"); }, + processOptionalGreeter(greeter) { return ""; }, + createOptionalGreeter() { return null; }, + handleAPIResult(result) { }, + getAPIResult() { return { tag: exports.APIResult.Tag.Info }; } + }; + + const managerWithOptional = new exports.DataProcessorManager(mainProcessor); + + assert.equal(managerWithOptional.backupProcessor, null); + assert.equal(managerWithOptional.hasBackup(), false); + assert.equal(managerWithOptional.getBackupValue(), null); + + managerWithOptional.backupProcessor = backupProcessor; + assert.notEqual(managerWithOptional.backupProcessor, null); + assert.equal(managerWithOptional.hasBackup(), true); + + managerWithOptional.incrementBoth(); + assert.equal(managerWithOptional.getCurrentValue(), 1); + assert.equal(managerWithOptional.getBackupValue(), 101); + + managerWithOptional.incrementBoth(); + assert.equal(managerWithOptional.getCurrentValue(), 2); + assert.equal(managerWithOptional.getBackupValue(), 102); + + managerWithOptional.backupProcessor = null; + assert.equal(managerWithOptional.backupProcessor, null); + assert.equal(managerWithOptional.hasBackup(), false); + + managerWithOptional.incrementBoth(); + assert.equal(managerWithOptional.getCurrentValue(), 3); + assert.equal(managerWithOptional.getBackupValue(), null); + + const swiftBackup = new exports.SwiftDataProcessor(); + managerWithOptional.backupProcessor = swiftBackup; + + assert.equal(managerWithOptional.hasBackup(), true); + assert.equal(managerWithOptional.getBackupValue(), 0); + + managerWithOptional.incrementBoth(); + assert.equal(managerWithOptional.getCurrentValue(), 4); + assert.equal(managerWithOptional.getBackupValue(), 1); + + managerWithOptional.release(); + swiftBackup.release(); +} diff --git a/Utilities/bridge-js-generate.sh b/Utilities/bridge-js-generate.sh index b79befa2b..22182d24b 100755 --- a/Utilities/bridge-js-generate.sh +++ b/Utilities/bridge-js-generate.sh @@ -1,6 +1,10 @@ #!/usr/bin/env bash -env JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package plugin --allow-writing-to-package-directory bridge-js -env JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --package-path ./Benchmarks plugin --allow-writing-to-package-directory bridge-js -env JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --package-path ./Examples/PlayBridgeJS plugin --allow-writing-to-package-directory bridge-js +set -euxo pipefail +swift build --package-path ./Plugins/BridgeJS --product BridgeJSTool + +./Plugins/BridgeJS/.build/debug/BridgeJSTool generate --project ./tsconfig.json --module-name BridgeJSRuntimeTests --target-dir ./Tests/BridgeJSRuntimeTests --output-dir ./Tests/BridgeJSRuntimeTests/Generated +./Plugins/BridgeJS/.build/debug/BridgeJSTool generate --project ./tsconfig.json --module-name BridgeJSGlobalTests --target-dir ./Tests/BridgeJSGlobalTests --output-dir ./Tests/BridgeJSGlobalTests/Generated +./Plugins/BridgeJS/.build/debug/BridgeJSTool generate --project ./tsconfig.json --module-name Benchmarks --target-dir ./Benchmarks/Sources --output-dir ./Benchmarks/Sources/Generated +./Plugins/BridgeJS/.build/debug/BridgeJSTool generate --project ./tsconfig.json --module-name PlayBridgeJS --target-dir ./Examples/PlayBridgeJS/Sources/PlayBridgeJS --output-dir ./Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated diff --git a/Utilities/build-examples.sh b/Utilities/build-examples.sh index 2b51307d3..bc84e6943 100755 --- a/Utilities/build-examples.sh +++ b/Utilities/build-examples.sh @@ -2,11 +2,25 @@ set -euo pipefail +EXCLUDED_EXAMPLES=() + for example in Examples/*; do + skip_example=false + for excluded in "${EXCLUDED_EXAMPLES[@]}"; do + if [[ "$example" == *"$excluded"* ]]; then + skip_example=true + break + fi + done + if [ "$skip_example" = true ]; then + echo "Skipping $example" + continue + fi + if [ -d "$example" ] && [ -f "$example/build.sh" ]; then echo "Building $example" set -x (cd "$example" && ./build.sh release) { set +x; } 2>/dev/null fi -done \ No newline at end of file +done diff --git a/Utilities/format.swift b/Utilities/format.swift index 9df282ad7..d26cbe2f3 100755 --- a/Utilities/format.swift +++ b/Utilities/format.swift @@ -38,7 +38,7 @@ func which(_ executable: String) -> URL? { /// Runs the `swift-format` command with the given arguments in the project root. func swiftFormat(_ arguments: [String]) throws { - guard let swiftFormat = which("swift-format") else { + guard let swiftFormat = which("swift") else { print("swift-format not found in PATH") exit(1) } @@ -93,7 +93,7 @@ switch arguments.first { case "lint": try swiftFormat(["lint", "--parallel", "--recursive"] + filesToFormat()) case "format", nil: - try swiftFormat(["format", "--parallel", "--in-place", "--recursive"] + filesToFormat()) + try swiftFormat(["format", "format", "--parallel", "--in-place", "--recursive"] + filesToFormat()) case let subcommand?: print("Unknown subcommand: \(subcommand)") print("Usage: format.swift lint|format") diff --git a/Utilities/prepare-gh-pages.sh b/Utilities/prepare-gh-pages.sh new file mode 100755 index 000000000..7260717a6 --- /dev/null +++ b/Utilities/prepare-gh-pages.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +mkdir -p ./_site +# Copy all files from ./Examples to ./_site, excluding specified path patterns +rsync -av --progress ./Examples/ ./_site/ --exclude=".build" +cat < _site/index.html + + + + + Redirecting... + + +

If you are not redirected automatically, follow this link to JavaScriptKit documentation.

+ + +EOF + diff --git a/package-lock.json b/package-lock.json index e12af9c97..9366b618d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,9 @@ "prettier": "3.5.3", "rollup": "^4.37.0", "rollup-plugin-dts": "^6.2.1", - "typescript": "^5.8.2" + "tslib": "^2.8.1", + "typescript": "^5.8.2", + "vitest": "^4.0.18" } }, "node_modules/@babel/code-frame": { @@ -50,11 +52,454 @@ "integrity": "sha512-54kpBQX69TZ8I1zyDC8sziv/zPT1zoIadv3CmdIZNZ5WDF1houMjAzRZ3dwWvhXObiEBjOxXyS8Ja7vA0EfGEQ==", "dev": true }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" }, "node_modules/@rollup/plugin-typescript": { "version": "12.1.2", @@ -107,9 +552,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.37.0.tgz", - "integrity": "sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", + "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", "cpu": [ "arm" ], @@ -121,9 +566,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.37.0.tgz", - "integrity": "sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", + "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", "cpu": [ "arm64" ], @@ -135,9 +580,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.37.0.tgz", - "integrity": "sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", + "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", "cpu": [ "arm64" ], @@ -149,9 +594,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.37.0.tgz", - "integrity": "sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", + "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", "cpu": [ "x64" ], @@ -163,9 +608,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.37.0.tgz", - "integrity": "sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", + "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", "cpu": [ "arm64" ], @@ -177,9 +622,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.37.0.tgz", - "integrity": "sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", + "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", "cpu": [ "x64" ], @@ -191,9 +636,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.37.0.tgz", - "integrity": "sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", + "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", "cpu": [ "arm" ], @@ -205,9 +650,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.37.0.tgz", - "integrity": "sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", + "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", "cpu": [ "arm" ], @@ -219,9 +664,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.37.0.tgz", - "integrity": "sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", + "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", "cpu": [ "arm64" ], @@ -233,9 +678,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.37.0.tgz", - "integrity": "sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", + "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", "cpu": [ "arm64" ], @@ -246,10 +691,24 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.37.0.tgz", - "integrity": "sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", + "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", + "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", "cpu": [ "loong64" ], @@ -260,10 +719,24 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.37.0.tgz", - "integrity": "sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ==", + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", + "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", + "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", "cpu": [ "ppc64" ], @@ -275,9 +748,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.37.0.tgz", - "integrity": "sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", + "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", "cpu": [ "riscv64" ], @@ -289,9 +762,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.37.0.tgz", - "integrity": "sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", + "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", "cpu": [ "riscv64" ], @@ -303,9 +776,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.37.0.tgz", - "integrity": "sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", + "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", "cpu": [ "s390x" ], @@ -316,90 +789,348 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.37.0.tgz", - "integrity": "sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ==", - "cpu": [ - "x64" - ], + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", + "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", + "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", + "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", + "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", + "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", + "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", + "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", + "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.13.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.14.tgz", + "integrity": "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==", + "dev": true, + "peer": true, + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@vitest/expect": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", + "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.0.18", + "@vitest/utils": "4.0.18", + "chai": "^6.2.1", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", + "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.0.18", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", + "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", + "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.0.18", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", + "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@vitest/pretty-format": "4.0.18", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.37.0.tgz", - "integrity": "sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w==", - "cpu": [ - "x64" - ], + "node_modules/@vitest/spy": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", + "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "funding": { + "url": "https://opencollective.com/vitest" + } }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.37.0.tgz", - "integrity": "sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg==", - "cpu": [ - "arm64" - ], + "node_modules/@vitest/utils": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", + "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@vitest/pretty-format": "4.0.18", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.37.0.tgz", - "integrity": "sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA==", - "cpu": [ - "ia32" - ], + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "engines": { + "node": ">=12" + } }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.37.0.tgz", - "integrity": "sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA==", - "cpu": [ - "x64" - ], + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "engines": { + "node": ">=18" + } }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, "license": "MIT" }, - "node_modules/@types/node": { - "version": "22.13.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.14.tgz", - "integrity": "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==", + "node_modules/esbuild": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", "dev": true, - "dependencies": { - "undici-types": "~6.20.0" + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" } }, "node_modules/estree-walker": { @@ -409,6 +1140,34 @@ "dev": true, "license": "MIT" }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -471,14 +1230,45 @@ "optional": true }, "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -486,17 +1276,23 @@ "dev": true, "license": "MIT" }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "optional": true + "dev": true }, "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -507,12 +1303,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 +1322,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" }, @@ -536,6 +1334,35 @@ "node": ">=18" } }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/prettier": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", @@ -574,13 +1401,14 @@ } }, "node_modules/rollup": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.37.0.tgz", - "integrity": "sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", + "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@types/estree": "1.0.6" + "@types/estree": "1.0.8" }, "bin": { "rollup": "dist/bin/rollup" @@ -590,26 +1418,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.37.0", - "@rollup/rollup-android-arm64": "4.37.0", - "@rollup/rollup-darwin-arm64": "4.37.0", - "@rollup/rollup-darwin-x64": "4.37.0", - "@rollup/rollup-freebsd-arm64": "4.37.0", - "@rollup/rollup-freebsd-x64": "4.37.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.37.0", - "@rollup/rollup-linux-arm-musleabihf": "4.37.0", - "@rollup/rollup-linux-arm64-gnu": "4.37.0", - "@rollup/rollup-linux-arm64-musl": "4.37.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.37.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.37.0", - "@rollup/rollup-linux-riscv64-gnu": "4.37.0", - "@rollup/rollup-linux-riscv64-musl": "4.37.0", - "@rollup/rollup-linux-s390x-gnu": "4.37.0", - "@rollup/rollup-linux-x64-gnu": "4.37.0", - "@rollup/rollup-linux-x64-musl": "4.37.0", - "@rollup/rollup-win32-arm64-msvc": "4.37.0", - "@rollup/rollup-win32-ia32-msvc": "4.37.0", - "@rollup/rollup-win32-x64-msvc": "4.37.0", + "@rollup/rollup-android-arm-eabi": "4.57.1", + "@rollup/rollup-android-arm64": "4.57.1", + "@rollup/rollup-darwin-arm64": "4.57.1", + "@rollup/rollup-darwin-x64": "4.57.1", + "@rollup/rollup-freebsd-arm64": "4.57.1", + "@rollup/rollup-freebsd-x64": "4.57.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", + "@rollup/rollup-linux-arm-musleabihf": "4.57.1", + "@rollup/rollup-linux-arm64-gnu": "4.57.1", + "@rollup/rollup-linux-arm64-musl": "4.57.1", + "@rollup/rollup-linux-loong64-gnu": "4.57.1", + "@rollup/rollup-linux-loong64-musl": "4.57.1", + "@rollup/rollup-linux-ppc64-gnu": "4.57.1", + "@rollup/rollup-linux-ppc64-musl": "4.57.1", + "@rollup/rollup-linux-riscv64-gnu": "4.57.1", + "@rollup/rollup-linux-riscv64-musl": "4.57.1", + "@rollup/rollup-linux-s390x-gnu": "4.57.1", + "@rollup/rollup-linux-x64-gnu": "4.57.1", + "@rollup/rollup-linux-x64-musl": "4.57.1", + "@rollup/rollup-openbsd-x64": "4.57.1", + "@rollup/rollup-openharmony-arm64": "4.57.1", + "@rollup/rollup-win32-arm64-msvc": "4.57.1", + "@rollup/rollup-win32-ia32-msvc": "4.57.1", + "@rollup/rollup-win32-x64-gnu": "4.57.1", + "@rollup/rollup-win32-x64-msvc": "4.57.1", "fsevents": "~2.3.2" } }, @@ -635,6 +1468,37 @@ "typescript": "^4.5 || ^5.0" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -648,13 +1512,56 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyrainbow": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", + "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD", - "optional": true, "peer": true }, "node_modules/typescript": { @@ -663,6 +1570,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" @@ -676,6 +1584,191 @@ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", "dev": true + }, + "node_modules/vite": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/vitest": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", + "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.0.18", + "@vitest/mocker": "4.0.18", + "@vitest/pretty-format": "4.0.18", + "@vitest/runner": "4.0.18", + "@vitest/snapshot": "4.0.18", + "@vitest/spy": "4.0.18", + "@vitest/utils": "4.0.18", + "es-module-lexer": "^1.7.0", + "expect-type": "^1.2.2", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^3.10.0", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3", + "vite": "^6.0.0 || ^7.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.0.18", + "@vitest/browser-preview": "4.0.18", + "@vitest/browser-webdriverio": "4.0.18", + "@vitest/ui": "4.0.18", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } } } } diff --git a/package.json b/package.json index 96443ad9a..509cddde2 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "build:clean": "rm -rf Runtime/lib", "build:ts": "cd Runtime; rollup -c", "prepublishOnly": "npm run build", - "format": "prettier --write Runtime/src" + "format": "prettier --write Runtime/src", + "check:bridgejs-dts": "tsc --project Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/tsconfig.json" }, "keywords": [ "Swift", @@ -41,6 +42,8 @@ "prettier": "3.5.3", "rollup": "^4.37.0", "rollup-plugin-dts": "^6.2.1", - "typescript": "^5.8.2" + "tslib": "^2.8.1", + "typescript": "^5.8.2", + "vitest": "^4.0.18" } } diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..c13ef64e3 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "strict": true, + "skipLibCheck": true + } +}